Skip to content

Commit

Permalink
add validation for unreacting comments/threads, fix delete reaction
Browse files Browse the repository at this point in the history
  • Loading branch information
raykyri committed Aug 2, 2024
1 parent 7661aae commit e99a197
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 23 deletions.
10 changes: 4 additions & 6 deletions libs/shared/src/canvas/runtime/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ export const contract = {
id: 'primary',
thread_id: '@threads.id?',
author: 'string',
value: 'string',
value: 'string?',
updated_at: 'integer',
$indexes: [['thread_id', 'author']],
},
comment_reactions: {
id: 'primary',
comment_id: '@comments.id?',
author: 'string',
value: 'string',
value: 'string?',
updated_at: 'integer',
$indexes: [['comment_id', 'author']],
},
Expand All @@ -58,12 +58,12 @@ export const contract = {
async updateThread(db, { thread_id, title, body, link, topic }, { did, id, timestamp }) {
const t = await db.get("threads", thread_id);
if (!t || !t.id) throw new Error("invalid thread");
db.set('threads', { id: t.id, author: t.author, community: t.community, title, body, link, topic, updated_at: timestamp });
db.set('threads', { id: t.id as string, author: t.author, community: t.community, title, body, link, topic, updated_at: timestamp });
},
async deleteThread(db, { thread_id }, { did, id }) {
const t = await db.get("threads", thread_id);
if (!t || !t.id) throw new Error("invalid thread");
db.delete("threads", t.id);
db.delete("threads", t.id as string);
},
async comment(db, { thread_id, body, parent_comment_id }, { did, id, timestamp }) {
db.set("comments", {
Expand Down Expand Up @@ -98,7 +98,6 @@ export const contract = {
updated_at: timestamp,
});
},
// TODO: signed on client, not verified on server (packages/commonwealth/server/routes/reactions/delete_reaction_handler.ts)
async unreactThread(db, { thread_id, value }, { did, id, timestamp }) {
db.set("thread_reactions", {
id: `${thread_id}/${did}`,
Expand All @@ -120,7 +119,6 @@ export const contract = {
updated_at: timestamp,
});
},
// TODO: signed on client, not verified on server (packages/commonwealth/server/routes/reactions/delete_reaction_handler.ts)
async unreactComment(db, { comment_id, value }, { did, id, timestamp }) {
db.set("comment_reactions", {
id: `${comment_id}/${did}`,
Expand Down
16 changes: 7 additions & 9 deletions libs/shared/src/canvas/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,25 +208,23 @@ export const verifyReaction = async (

export const verifyDeleteReaction = async (
canvasSignedData: CanvasSignedData,
fields: any,
fields: { comment_id: string } | { thread_id: string },
) => {
const { id } = fields;

await verify(canvasSignedData);

const { actionMessage } = canvasSignedData;
if (actionMessage.payload.name == 'unreactThread') {
if (actionMessage.payload.name === 'unreactThread') {
assertMatches(
actionMessage.payload.args.thread_id,
parseInt(id),
'thread',
fields.thread_id,
'reactThread',
'thread_id',
);
} else if (actionMessage.payload.name == 'unreactComment') {
} else if (actionMessage.payload.name === 'unreactComment') {
assertMatches(
actionMessage.payload.args.comment_id,
parseInt(id),
'comment',
fields.comment_id,
'reactComment',
'comment_id',
);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ export const CommentReactionButton = ({
deleteCommentReaction({
communityId: app.activeChainId(),
address: user.activeAccount?.address,
// @ts-expect-error <StrictNullChecks/>
canvasMsgId: foundReaction.canvasMsgId,
// @ts-expect-error <StrictNullChecks/>
reactionMsgId: foundReaction.canvasMsgId,
reactionId: foundReaction.id,
}).catch((err) => {
if (err instanceof SessionKeyError) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { CommentAttributes } from '@hicommonwealth/model';
import {
applyCanvasSignedData,
fromCanvasSignedDataApiArgs,
hasCanvasSignedDataApiArgs,
verifyDeleteComment,
} from '@hicommonwealth/shared';
import { canvas } from 'server';
import { DeleteCommentOptions } from 'server/controllers/server_comments_methods/delete_comment';
import { config } from '../../config';
import { ServerControllers } from '../../routing/router';
Expand Down Expand Up @@ -44,5 +46,13 @@ export const deleteCommentHandler = async (

await controllers.comments.deleteComment(commentFields);

// publish signed data
if (hasCanvasSignedDataApiArgs(req.body)) {
const { canvasSignedData } = fromCanvasSignedDataApiArgs(req.body);
if (canvasSignedData.actionMessage.payload.args.comment_id !== null) {
await applyCanvasSignedData(canvas, canvasSignedData);
}
}

return success(res, undefined);
};
Original file line number Diff line number Diff line change
@@ -1,24 +1,62 @@
import { AppError } from '@hicommonwealth/core';
import {
applyCanvasSignedData,
fromCanvasSignedDataApiArgs,
hasCanvasSignedDataApiArgs,
verifyDeleteReaction,
} from '@hicommonwealth/shared';
import { canvas } from 'server';
import { ServerControllers } from 'server/routing/router';
import { TypedRequestParams, TypedResponse, success } from '../../types';
import { config } from '../../config';
import { TypedRequest, TypedResponse, success } from '../../types';

const Errors = {
InvalidReactionId: 'Invalid reaction ID',
};

type DeleteReactionRequest = { id: string };
type DeleteReactionRequestBody = {
canvas_signed_data?: string;
canvas_msg_id?: string;
};
type DeleteReactionRequestParams = {
id: string;
};
type DeleteReactionResponse = undefined;

export const deleteReactionHandler = async (
controllers: ServerControllers,
req: TypedRequestParams<DeleteReactionRequest>,
req: TypedRequest<DeleteReactionRequestBody, {}, DeleteReactionRequestParams>,
res: TypedResponse<DeleteReactionResponse>,
) => {
const reactionId = parseInt(req.params.id, 10);
const { id } = req.params!;
const reactionId = parseInt(id, 10);
if (!reactionId) {
throw new AppError(Errors.InvalidReactionId);
}

if (hasCanvasSignedDataApiArgs(req.body)) {
if (config.ENFORCE_SESSION_KEYS) {
const { canvasSignedData } = fromCanvasSignedDataApiArgs(req.body);
if (canvasSignedData.actionMessage.payload.name === 'unreactComment') {
const comment_msg_id =
canvasSignedData.actionMessage.payload.args.comment_id; // TODO
await verifyDeleteReaction(canvasSignedData, {
comment_id: comment_msg_id,
});
} else if (
canvasSignedData.actionMessage.payload.name === 'unreactThread'
) {
const thread_msg_id =
canvasSignedData.actionMessage.payload.args.thread_id; // TODO
await verifyDeleteReaction(canvasSignedData, {
thread_id: thread_msg_id,
});
} else {
throw new Error('unexpected signed message');
}
}
}

await controllers.reactions.deleteReaction({
// @ts-expect-error StrictNullChecks
user: req.user,
Expand All @@ -29,5 +67,10 @@ export const deleteReactionHandler = async (
reactionId,
});

if (hasCanvasSignedDataApiArgs(req.body)) {
const { canvasSignedData } = fromCanvasSignedDataApiArgs(req.body);
await applyCanvasSignedData(canvas, canvasSignedData);
}

return success(res, undefined);
};
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ export const deleteThreadHandler = async (
// publish signed data
if (hasCanvasSignedDataApiArgs(req.body)) {
const { canvasSignedData } = fromCanvasSignedDataApiArgs(req.body);
await applyCanvasSignedData(canvas, canvasSignedData);
if (canvasSignedData.actionMessage.payload.args.thread_id !== null) {
await applyCanvasSignedData(canvas, canvasSignedData);
}
}

return success(res, undefined);
Expand Down

0 comments on commit e99a197

Please sign in to comment.