Check owner, member and author prior handling (#283)
* check owner, member and author * fix isOwner
This commit is contained in:
parent
fa30667c51
commit
f26d429a9d
|
@ -25,6 +25,7 @@ export type ChatMessage = ChatMessageProto & {
|
|||
pinned: boolean
|
||||
reactions: Reactions
|
||||
chatUuid: string
|
||||
signer: string
|
||||
responseToMessage?: Omit<ChatMessage, 'responseToMessage'>
|
||||
}
|
||||
|
||||
|
@ -215,7 +216,11 @@ export class Chat {
|
|||
this.emitMessages(this.messages)
|
||||
}
|
||||
|
||||
public handleEditedMessage = (messageId: string, text: string) => {
|
||||
public handleEditedMessage = (
|
||||
messageId: string,
|
||||
text: string,
|
||||
signerPublicKey: string
|
||||
) => {
|
||||
let messageIndex = this.messages.length
|
||||
while (--messageIndex >= 0) {
|
||||
const _message = this.messages[messageIndex]
|
||||
|
@ -230,6 +235,10 @@ export class Chat {
|
|||
return
|
||||
}
|
||||
|
||||
if (!this.isAuthor(this.messages[messageIndex], signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
this.messages[messageIndex] = {
|
||||
...this.messages[messageIndex],
|
||||
text,
|
||||
|
@ -239,7 +248,10 @@ export class Chat {
|
|||
this.emitMessages(this.messages)
|
||||
}
|
||||
|
||||
public handleDeletedMessage = (messageId: string) => {
|
||||
public handleDeletedMessage = (
|
||||
messageId: string,
|
||||
signerPublicKey: string
|
||||
) => {
|
||||
let messageIndex = this.messages.length
|
||||
while (--messageIndex >= 0) {
|
||||
const _message = this.messages[messageIndex]
|
||||
|
@ -253,6 +265,10 @@ export class Chat {
|
|||
return
|
||||
}
|
||||
|
||||
if (!this.isAuthor(this.messages[messageIndex], signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
this.messages.splice(messageIndex, 1)
|
||||
|
||||
this.emitMessages(this.messages)
|
||||
|
@ -380,7 +396,31 @@ export class Chat {
|
|||
}
|
||||
|
||||
public editMessage = async (messageId: string, text: string) => {
|
||||
// todo?: check if message exists
|
||||
if (!this.client.account) {
|
||||
throw new Error('Text message cannot be edited without a created account')
|
||||
}
|
||||
|
||||
let messageIndex = this.messages.length
|
||||
while (--messageIndex >= 0) {
|
||||
const _message = this.messages[messageIndex]
|
||||
|
||||
if (_message.messageId === messageId) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (messageIndex < 0) {
|
||||
throw new Error('Text message was not found')
|
||||
}
|
||||
|
||||
if (
|
||||
!this.isAuthor(
|
||||
this.messages[messageIndex],
|
||||
`0x${this.client.account.publicKey}`
|
||||
)
|
||||
) {
|
||||
throw new Error('Text message can only be edited by its author')
|
||||
}
|
||||
|
||||
if (text === '') {
|
||||
throw new Error('Text message cannot be empty')
|
||||
|
@ -404,7 +444,33 @@ export class Chat {
|
|||
}
|
||||
|
||||
public deleteMessage = async (messageId: string) => {
|
||||
// todo: check if message exists
|
||||
if (!this.client.account) {
|
||||
throw new Error(
|
||||
'Text message cannot be deleted without a created account'
|
||||
)
|
||||
}
|
||||
|
||||
let messageIndex = this.messages.length
|
||||
while (--messageIndex >= 0) {
|
||||
const _message = this.messages[messageIndex]
|
||||
|
||||
if (_message.messageId === messageId) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (messageIndex < 0) {
|
||||
throw new Error('Text message was not found')
|
||||
}
|
||||
|
||||
if (
|
||||
!this.isAuthor(
|
||||
this.messages[messageIndex],
|
||||
`0x${this.client.account.publicKey}`
|
||||
)
|
||||
) {
|
||||
throw new Error('Text message can only be deleted by its author')
|
||||
}
|
||||
|
||||
const payload = DeleteMessage.encode({
|
||||
clock: BigInt(Date.now()),
|
||||
|
@ -457,4 +523,11 @@ export class Chat {
|
|||
this.symmetricKey
|
||||
)
|
||||
}
|
||||
|
||||
public isAuthor = (
|
||||
message: ChatMessage,
|
||||
signerPublicKey: string
|
||||
): boolean => {
|
||||
return message.signer === signerPublicKey
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import { CommunityRequestToJoin } from '~/protos/communities'
|
|||
import { MessageType } from '~/protos/enums'
|
||||
import { getDifferenceByKeys } from '~/src/helpers/get-difference-by-keys'
|
||||
import { getObjectsDifference } from '~/src/helpers/get-objects-difference'
|
||||
import { compressPublicKey } from '~/src/utils/compress-public-key'
|
||||
|
||||
import { idToContentTopic } from '../../contentTopic'
|
||||
import { createSymKeyFromPassword } from '../../encryption'
|
||||
|
@ -20,6 +21,7 @@ import type {
|
|||
export class Community {
|
||||
private client: Client
|
||||
|
||||
/** Compressed. */
|
||||
public publicKey: string
|
||||
public id: string
|
||||
private contentTopic!: string
|
||||
|
@ -254,4 +256,15 @@ export class Community {
|
|||
this.symmetricKey
|
||||
)
|
||||
}
|
||||
|
||||
public isOwner = (
|
||||
/** Uncompressed. */
|
||||
signerPublicKey: string
|
||||
): boolean => {
|
||||
return this.publicKey === `0x${compressPublicKey(signerPublicKey)}`
|
||||
}
|
||||
|
||||
public isMember = (signerPublicKey: string): boolean => {
|
||||
return this.getMember(signerPublicKey) !== undefined
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,15 +52,16 @@ export function handleWakuMessage(
|
|||
}
|
||||
messageToDecode = decodedMetadata.payload
|
||||
|
||||
const publicKey = recoverPublicKey(
|
||||
const signerPublicKeyBytes = recoverPublicKey(
|
||||
decodedMetadata.signature,
|
||||
decodedMetadata.payload
|
||||
)
|
||||
|
||||
const messageId = payloadToId(
|
||||
decodedProtocol?.publicMessage ?? wakuMessage.payload,
|
||||
publicKey
|
||||
signerPublicKeyBytes
|
||||
)
|
||||
const signerPublicKey = `0x${bytesToHex(signerPublicKeyBytes)}`
|
||||
|
||||
// already handled
|
||||
if (client.wakuMessages.has(messageId)) {
|
||||
|
@ -76,6 +77,10 @@ export function handleWakuMessage(
|
|||
// decode
|
||||
const decodedPayload = CommunityDescription.decode(messageToDecode)
|
||||
|
||||
if (!community.isOwner(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
// handle (state and callback)
|
||||
community.handleDescription(decodedPayload)
|
||||
|
||||
|
@ -88,16 +93,26 @@ export function handleWakuMessage(
|
|||
|
||||
switch (decodedPayload.messageType) {
|
||||
case MessageType.COMMUNITY_CHAT: {
|
||||
if (!community.isMember(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const chatUuid = getChatUuid(decodedPayload.chatId)
|
||||
const chat = community.chats.get(chatUuid)
|
||||
|
||||
if (!chat) {
|
||||
return
|
||||
}
|
||||
|
||||
// map
|
||||
const chatMessage = mapChatMessage(decodedPayload, {
|
||||
messageId,
|
||||
chatUuid,
|
||||
signerPublicKey,
|
||||
})
|
||||
|
||||
// handle
|
||||
community.chats.get(chatUuid)?.handleNewMessage(chatMessage)
|
||||
chat.handleNewMessage(chatMessage)
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -115,12 +130,23 @@ export function handleWakuMessage(
|
|||
|
||||
switch (decodedPayload.messageType) {
|
||||
case MessageType.COMMUNITY_CHAT: {
|
||||
if (!community.isMember(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const messageId = decodedPayload.messageId
|
||||
const chatUuid = getChatUuid(decodedPayload.chatId)
|
||||
const chat = community.chats.get(chatUuid)
|
||||
|
||||
community.chats
|
||||
.get(chatUuid)
|
||||
?.handleEditedMessage(messageId, decodedPayload.text)
|
||||
if (!chat) {
|
||||
return
|
||||
}
|
||||
|
||||
chat.handleEditedMessage(
|
||||
messageId,
|
||||
decodedPayload.text,
|
||||
signerPublicKey
|
||||
)
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -138,10 +164,19 @@ export function handleWakuMessage(
|
|||
|
||||
switch (decodedPayload.messageType) {
|
||||
case MessageType.COMMUNITY_CHAT: {
|
||||
if (!community.isMember(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const messageId = decodedPayload.messageId
|
||||
const chatUuid = getChatUuid(decodedPayload.chatId)
|
||||
const chat = community.chats.get(chatUuid)
|
||||
|
||||
community.chats.get(chatUuid)?.handleDeletedMessage(messageId)
|
||||
if (!chat) {
|
||||
return
|
||||
}
|
||||
|
||||
chat.handleDeletedMessage(messageId, signerPublicKey)
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -159,12 +194,19 @@ export function handleWakuMessage(
|
|||
|
||||
switch (decodedPayload.messageType) {
|
||||
case MessageType.COMMUNITY_CHAT: {
|
||||
if (!community.isMember(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const messageId = decodedPayload.messageId
|
||||
const chatUuid = getChatUuid(decodedPayload.chatId)
|
||||
const chat = community.chats.get(chatUuid)
|
||||
|
||||
community.chats
|
||||
.get(chatUuid)
|
||||
?.handlePinnedMessage(messageId, decodedPayload.pinned)
|
||||
if (!chat) {
|
||||
return
|
||||
}
|
||||
|
||||
chat.handlePinnedMessage(messageId, decodedPayload.pinned)
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -182,16 +224,19 @@ export function handleWakuMessage(
|
|||
|
||||
switch (decodedPayload.messageType) {
|
||||
case MessageType.COMMUNITY_CHAT: {
|
||||
if (!community.isMember(signerPublicKey)) {
|
||||
return
|
||||
}
|
||||
|
||||
const messageId = decodedPayload.messageId
|
||||
const chatUuid = getChatUuid(decodedPayload.chatId)
|
||||
|
||||
const chat = community.chats.get(chatUuid)
|
||||
|
||||
chat?.handleEmojiReaction(
|
||||
messageId,
|
||||
decodedPayload,
|
||||
`0x${bytesToHex(publicKey)}`
|
||||
)
|
||||
if (!chat) {
|
||||
return
|
||||
}
|
||||
|
||||
chat.handleEmojiReaction(messageId, decodedPayload, signerPublicKey)
|
||||
|
||||
break
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@ export function mapChatMessage(
|
|||
props: {
|
||||
messageId: string
|
||||
chatUuid: string
|
||||
publicKey: string
|
||||
signerPublicKey: string
|
||||
}
|
||||
): ChatMessage {
|
||||
const { messageId, chatUuid, publicKey } = props
|
||||
const { messageId, chatUuid, signerPublicKey } = props
|
||||
|
||||
const message = {
|
||||
const message: ChatMessage = {
|
||||
...decodedMessage,
|
||||
messageId,
|
||||
chatUuid,
|
||||
pinned: false,
|
||||
signer: publicKey,
|
||||
signer: signerPublicKey,
|
||||
reactions: {
|
||||
THUMBS_UP: new Set<string>(),
|
||||
THUMBS_DOWN: new Set<string>(),
|
||||
|
|
Loading…
Reference in New Issue