Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transfer /viewComments + comment spam routes to new framework #9628

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
12 changes: 10 additions & 2 deletions libs/model/src/comment/GetComments.query.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type Query } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { removeUndefined } from '../utils/index';
import { removeUndefined, sanitizeDeletedComment } from '../utils/index';
import { formatSequelizePagination } from '../utils/paginationUtils';

export function GetComments(): Query<typeof schemas.GetComments> {
Expand Down Expand Up @@ -58,7 +58,15 @@ export function GetComments(): Query<typeof schemas.GetComments> {
paranoid: false,
});

return schemas.buildPaginatedResponse(comments, count as number, payload);
const sanitizedComments = comments.map((c) => {
const data = c.toJSON();
return {
...sanitizeDeletedComment(data),
last_edited: data.updated_at,
};
});

return schemas.buildPaginatedResponse(sanitizedComments, count, payload);
},
};
}
37 changes: 37 additions & 0 deletions libs/model/src/comment/SetCommentSpam.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { InvalidState, type Command } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { isAuthorized, type AuthContext } from '../middleware';

export const MarkCommentAsSpamErrors = {
CommentNotFound: 'Could not find Comment',
};

export function SetCommentSpam(): Command<
typeof schemas.SetCommentSpam,
AuthContext
> {
return {
...schemas.SetCommentSpam,
auth: [isAuthorized({ roles: ['admin', 'moderator'] })],
body: async ({ payload }) => {
const comment = await models.Comment.findOne({
where: { id: payload.comment_id },
include: [{ model: models.Thread, attributes: ['community_id'] }],
});
if (!comment) {
throw new InvalidState(MarkCommentAsSpamErrors.CommentNotFound);
}

if (payload.spam && !comment.marked_as_spam_at) {
comment.marked_as_spam_at = new Date();
await comment.save();
} else if (!payload.spam && comment.marked_as_spam_at) {
comment.marked_as_spam_at = null;
await comment.save();
}

return comment;
},
};
}
74 changes: 74 additions & 0 deletions libs/model/src/comment/ViewComments.query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { type Query } from '@hicommonwealth/core';
import * as schemas from '@hicommonwealth/schemas';
import { models } from '../database';
import { sanitizeDeletedComment } from '../utils/sanitizeDeletedComment';

export function ViewComments(): Query<typeof schemas.ViewComments> {
return {
...schemas.ViewComments,
auth: [],
body: async ({ payload }) => {
const comments = await models.Comment.findAll({
include: [
{
model: models.Address,
required: true,
include: [
{
model: models.User,
as: 'User',
required: true,
attributes: ['id', 'profile'],
},
],
},
{
model: models.Thread,
attributes: ['id'],
required: true,
where: { id: payload.thread_id },
},
{
model: models.Reaction,
as: 'reactions',
include: [
{
model: models.Address,
as: 'Address',
required: true,
attributes: ['address', 'last_active'],
include: [
{
model: models.User,
as: 'User',
required: true,
attributes: ['id', 'profile'],
},
],
},
],
},
{
model: models.CommentVersionHistory,
},
],
order: [['created_at', 'DESC']],
paranoid: false,
});

return comments.map((c) => {
const data = c.toJSON();
return {
...sanitizeDeletedComment(data),
last_edited: data.updated_at?.toISOString(),
community_id: data.Thread!.community_id!,
Address: {
...data.Address!,
User: data.Address!.User!,
},
Thread: data.Thread!,
};
});
},
};
}
2 changes: 2 additions & 0 deletions libs/model/src/comment/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ export * from './CreateCommentReaction.command';
export * from './DeleteComment.command';
export * from './GetComments.query';
export * from './SearchComments.query';
export * from './SetCommentSpam.command';
export * from './UpdateComment.command';
export * from './ViewComments.query';
1 change: 1 addition & 0 deletions libs/model/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './denormalizedCountUtils';
export * from './getDelta';
export * from './makeGetBalancesOptions';
export * from './parseUserMentions';
export * from './sanitizeDeletedComment';
export * from './sanitizeQuillText';
export * from './updateTags';
export * from './utils';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CommentAttributes } from '@hicommonwealth/model';
import { CommentAttributes } from '../models/comment';

export function sanitizeDeletedComment(
comment: CommentAttributes,
Expand Down
8 changes: 8 additions & 0 deletions libs/schemas/src/commands/comment.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,11 @@ export const DeleteComment = {
canvas_msg_id: z.string().nullish(),
}),
};

export const SetCommentSpam = {
input: z.object({
comment_id: PG_INT,
spam: z.boolean(),
}),
output: Comment,
};
21 changes: 19 additions & 2 deletions libs/schemas/src/queries/comment.schemas.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import z from 'zod';
import { Comment } from '../entities';
import { Address, Comment, Thread, User } from '../entities';
import { PG_INT, zBoolean } from '../utils';
import { PaginatedResultSchema, PaginationParamsSchema } from './pagination';

Expand All @@ -25,6 +25,23 @@ export const GetComments = {
include_reactions: zBoolean.default(false),
}),
output: PaginatedResultSchema.extend({
results: Comment.array(),
results: Comment.extend({
last_edited: z.coerce.date().optional(),
}).array(),
}),
};

// Similar to GetComments but used exclusively in our client (LEGACY)
export const ViewComments = {
input: z.object({
thread_id: PG_INT,
}),
output: Comment.extend({
last_edited: z.string().nullish(),
community_id: z.string(),
Address: Address.extend({
User: User,
}),
Thread: Thread,
}).array(),
};
Original file line number Diff line number Diff line change
@@ -1,45 +1,57 @@
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import { ViewComments } from '@hicommonwealth/schemas';
import Comment from 'models/Comment';
import app from 'state';
import { ApiEndpoints, SERVER_URL } from 'state/api/config';
import { trpc } from 'utils/trpcClient';
import { z } from 'zod';

const COMMENTS_STALE_TIME = 30 * 1_000; // 30 s

interface FetchCommentsProps {
threadId: number;
communityId: string;
apiEnabled?: boolean;
}

const fetchComments = async ({ communityId, threadId }: FetchCommentsProps) => {
const response = await axios.get(
`${SERVER_URL}${ApiEndpoints.FETCH_COMMENTS}`,
{
params: {
community_id: communityId || app.activeChainId(),
thread_id: threadId,
},
},
/**
* @Deprecated
*/
const mapToLegacyCommentsModel = async (

Check warning on line 11 in packages/commonwealth/client/scripts/state/api/comments/fetchComments.ts

View workflow job for this annotation

GitHub Actions / Code Quality Recommendations (20)

'mapToLegacyCommentsModel' is assigned a value but never used
comments: z.infer<typeof ViewComments.output>,
) => {
return comments.map(
(c) =>
new Comment({
id: c.id,
text: c.text,
author: c.Address.address,
community_id: c.community_id,
Address: c.Address,
thread_id: c.thread_id,
parent_id: c.parent_id,
// TODO: why is this not plural
reactions: c.Reaction,
reaction_weights_sum: c.reaction_weights_sum,
created_at: c.created_at,
deleted_at: c.deleted_at,
authorChain: c.Thread.community_id,
last_edited: c.last_edited,
canvas_signed_data: c.canvas_signed_data,
canvas_msg_id: c.canvas_msg_id,
CommentVersionHistories: c.CommentVersionHistories,
marked_as_spam_at: c.marked_as_spam_at,
discord_meta: c.discord_meta,
}),
);
};

// transform response
return response.data.result.map(
(c) => new Comment({ community_id: undefined, ...c }),
);
type useViewCommentsProps = z.infer<typeof ViewComments.input> & {
apiEnabled?: boolean;
};

const useFetchCommentsQuery = ({
communityId,
threadId,
thread_id,
apiEnabled = true,
}: FetchCommentsProps) => {
return useQuery({
queryKey: [ApiEndpoints.FETCH_COMMENTS, communityId, threadId],
queryFn: () => fetchComments({ communityId, threadId }),
staleTime: COMMENTS_STALE_TIME,
enabled: apiEnabled,
});
}: useViewCommentsProps) => {
return trpc.comment.viewComments.useQuery(
{ thread_id },
{
enabled: apiEnabled,
staleTime: COMMENTS_STALE_TIME,
},
);
};

export default useFetchCommentsQuery;
2 changes: 2 additions & 0 deletions packages/commonwealth/server/api/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ export const trpcRouter = trpc.router({
searchComments: trpc.query(Comment.SearchComments, trpc.Tag.Comment),
getComments: trpc.query(Comment.GetComments, trpc.Tag.Comment),
deleteComment: trpc.command(Comment.DeleteComment, trpc.Tag.Comment),
setCommentSpam: trpc.command(Comment.SetCommentSpam, trpc.Tag.Comment),
viewComments: trpc.query(Comment.ViewComments, trpc.Tag.Comment),
});
10 changes: 8 additions & 2 deletions packages/commonwealth/server/api/external-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ const {
deleteReaction,
deleteThread,
} = thread.trpcRouter;
const { createComment, updateComment, deleteComment, createCommentReaction } =
comment.trpcRouter;
const {
createComment,
updateComment,
deleteComment,
createCommentReaction,
setCommentSpam,
} = comment.trpcRouter;
const { getNewContent } = user.trpcRouter;

const api = {
Expand Down Expand Up @@ -82,6 +87,7 @@ const api = {
deleteReaction,
joinCommunity,
banAddress,
setCommentSpam,
};

const PATH = '/api/v1';
Expand Down
2 changes: 1 addition & 1 deletion packages/commonwealth/server/routes/viewComments.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppError } from '@hicommonwealth/core';
import type { DB } from '@hicommonwealth/model';
import { sanitizeDeletedComment } from '@hicommonwealth/model';
import type { NextFunction, Request, Response } from 'express';
import { sanitizeDeletedComment } from 'server/util/sanitizeDeletedComment';

export const Errors = {
NoRootId: 'Must provide thread_id',
Expand Down
Loading