Skip to content

Commit

Permalink
Merge pull request #9669 from hicommonwealth/tim/truncate-bodies-async
Browse files Browse the repository at this point in the history
  • Loading branch information
timolegros authored Nov 1, 2024
2 parents c1d1da7 + 6f40581 commit 86c026b
Show file tree
Hide file tree
Showing 18 changed files with 242 additions and 467 deletions.
5 changes: 4 additions & 1 deletion libs/model/src/models/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
ReactionAttributes,
ThreadInstance,
} from '.';
import { beforeValidateBodyHook } from './utils';

export type CommentAttributes = z.infer<typeof Comment> & {
// associations
Expand Down Expand Up @@ -68,6 +69,9 @@ export default (
},
{
hooks: {
beforeValidate(instance: CommentInstance) {
beforeValidateBodyHook(instance);
},
afterCreate: async (comment, options) => {
await (
sequelize.models.Thread as Sequelize.ModelStatic<ThreadInstance>
Expand All @@ -85,7 +89,6 @@ export default (
thread_id: String(comment.thread_id),
});
},

afterDestroy: async ({ thread_id }, options) => {
await (
sequelize.models.Thread as Sequelize.ModelStatic<ThreadInstance>
Expand Down
6 changes: 6 additions & 0 deletions libs/model/src/models/comment_version_history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Sequelize from 'sequelize';
import { z } from 'zod';
import { CommentAttributes } from './comment';
import type { ModelInstance } from './types';
import { beforeValidateBodyHook } from './utils';

export type CommentVersionHistoryAttributes = z.infer<
typeof CommentVersionHistory
Expand Down Expand Up @@ -30,5 +31,10 @@ export default (
tableName: 'CommentVersionHistories',
timestamps: false,
indexes: [{ fields: ['comment_id'] }],
hooks: {
beforeValidate(instance: CommentVersionHistoryInstance) {
beforeValidateBodyHook(instance);
},
},
},
);
6 changes: 5 additions & 1 deletion libs/model/src/models/thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AddressAttributes } from './address';
import type { CommunityAttributes } from './community';
import type { ThreadSubscriptionAttributes } from './thread_subscriptions';
import type { ModelInstance } from './types';
import { beforeValidateBodyHook } from './utils';

export type ThreadAttributes = z.infer<typeof Thread> & {
// associations
Expand All @@ -26,7 +27,7 @@ export default (
address_id: { type: Sequelize.INTEGER, allowNull: true },
created_by: { type: Sequelize.STRING, allowNull: true },
title: { type: Sequelize.TEXT, allowNull: false },
body: { type: Sequelize.TEXT, allowNull: true },
body: { type: Sequelize.TEXT, allowNull: false },
kind: { type: Sequelize.STRING, allowNull: false },
stage: {
type: Sequelize.TEXT,
Expand Down Expand Up @@ -116,6 +117,9 @@ export default (
{ fields: ['canvas_msg_id'] },
],
hooks: {
beforeValidate(instance: ThreadInstance) {
beforeValidateBodyHook(instance);
},
afterCreate: async (
thread: ThreadInstance,
options: Sequelize.CreateOptions<ThreadAttributes>,
Expand Down
6 changes: 6 additions & 0 deletions libs/model/src/models/thread_version_history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Sequelize from 'sequelize';
import { z } from 'zod';
import { ThreadAttributes } from './thread';
import type { ModelInstance } from './types';
import { beforeValidateBodyHook } from './utils';

export type ThreadVersionHistoryAttributes = z.infer<
typeof ThreadVersionHistory
Expand Down Expand Up @@ -31,5 +32,10 @@ export default (
tableName: 'ThreadVersionHistories',
timestamps: false,
indexes: [{ fields: ['thread_id'] }],
hooks: {
beforeValidate(instance: ThreadVersionHistoryInstance) {
beforeValidateBodyHook(instance);
},
},
},
);
26 changes: 25 additions & 1 deletion libs/model/src/models/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { decamelize } from '@hicommonwealth/shared';
import {
decamelize,
MAX_TRUNCATED_CONTENT_LENGTH,
safeTruncateBody,
} from '@hicommonwealth/shared';
import {
Model,
Sequelize,
Expand Down Expand Up @@ -278,3 +282,23 @@ export const syncHooks = {
options.logging = false;
},
};

export const beforeValidateBodyHook = (instance: {
body: string;
content_url?: string | null | undefined;
}) => {
if (!instance.body || instance.body.length <= MAX_TRUNCATED_CONTENT_LENGTH)
return;

if (!instance.content_url) {
throw new Error(
'content_url must be defined if body ' +
`length is greater than ${MAX_TRUNCATED_CONTENT_LENGTH}`,
);
} else
instance.body = safeTruncateBody(
instance.body,
MAX_TRUNCATED_CONTENT_LENGTH,
);
return instance;
};
1 change: 1 addition & 0 deletions libs/model/src/utils/validateGroupMembership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type ValidateGroupMembershipResponse = {
* @param userAddress address of user
* @param requirements An array of requirement types to be validated against
* @param balances address balances
* @param numRequiredRequirements
* @returns ValidateGroupMembershipResponse validity and messages on requirements that failed
*/
export function validateGroupMembership(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ describe('Contest Worker Policy', () => {
canvas_msg_id: '',
kind: '',
stage: '',
body: '',
view_count: 0,
reaction_count: 0,
reaction_weights_sum: '0',
Expand Down
27 changes: 18 additions & 9 deletions libs/model/test/thread/thread-lifecycle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as schemas from '@hicommonwealth/schemas';
import { TopicWeightedVoting } from '@hicommonwealth/schemas';
import {
CANVAS_TOPIC,
MAX_TRUNCATED_CONTENT_LENGTH,
getTestSigner,
sign,
toCanvasSignedDataApiArgs,
Expand Down Expand Up @@ -283,7 +284,6 @@ describe('Thread lifecycle', () => {
payload: await signPayload(actors[role].address!, instancePayload),
});
expect(_thread?.title).to.equal(instancePayload.title);
expect(_thread?.body).to.equal(instancePayload.body);
expect(_thread?.stage).to.equal(instancePayload.stage);
// capture as admin author for other tests
if (!thread) thread = _thread!;
Expand All @@ -296,6 +296,12 @@ describe('Thread lifecycle', () => {
key: _thread!.content_url!.split('/').pop()!,
}),
).toBeTruthy();

expect(_thread?.body).to.equal(
instancePayload.body.slice(0, MAX_TRUNCATED_CONTENT_LENGTH),
);
} else {
expect(_thread?.body).to.equal(instancePayload.body);
}
});
} else {
Expand All @@ -313,7 +319,7 @@ describe('Thread lifecycle', () => {

describe('updates', () => {
test('should patch content', async () => {
const body = {
const payloadContent = {
title: 'hello',
body: chance.paragraph({ sentences: 50 }),
canvas_msg_id: '',
Expand All @@ -323,10 +329,13 @@ describe('Thread lifecycle', () => {
actor: actors.admin,
payload: {
thread_id: thread.id!,
...body,
...payloadContent,
},
});
expect(updated).to.contain(body);
expect(updated).to.contain({
...payloadContent,
body: payloadContent.body.slice(0, MAX_TRUNCATED_CONTENT_LENGTH),
});
expect(updated?.content_url).toBeTruthy();
expect(
await blobStorage({ key: R2_ADAPTER_KEY }).exists({
Expand All @@ -336,15 +345,15 @@ describe('Thread lifecycle', () => {
).toBeTruthy();
expect(updated?.ThreadVersionHistories?.length).to.equal(2);

body.body = 'wasup';
payloadContent.body = 'wasup';
updated = await command(UpdateThread(), {
actor: actors.admin,
payload: {
thread_id: thread.id!,
...body,
...payloadContent,
},
});
expect(updated).to.contain(body);
expect(updated).to.contain(payloadContent);
expect(updated?.content_url).toBeFalsy();
expect(updated!.ThreadVersionHistories?.length).to.equal(3);
const sortedHistory = updated!.ThreadVersionHistories!.sort(
Expand Down Expand Up @@ -572,7 +581,7 @@ describe('Thread lifecycle', () => {
});
expect(firstComment).to.include({
thread_id: thread!.id,
body,
body: body.slice(0, MAX_TRUNCATED_CONTENT_LENGTH),
community_id: thread!.community_id,
});
expect(firstComment?.content_url).toBeTruthy();
Expand Down Expand Up @@ -713,7 +722,7 @@ describe('Thread lifecycle', () => {
});
expect(updated).to.include({
thread_id: thread!.id,
body,
body: body.slice(0, MAX_TRUNCATED_CONTENT_LENGTH),
community_id: thread!.community_id,
});
expect(updated?.content_url).toBeTruthy();
Expand Down
1 change: 1 addition & 0 deletions libs/model/test/util-tests/getCommentDepth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('getCommentDepth', () => {
});
const thread = await models.Thread.create({
community_id,
body: 'test',
address_id: address!.id!,
title: 'Testing',
kind: 'discussion',
Expand Down
2 changes: 1 addition & 1 deletion libs/schemas/src/entities/thread.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const Thread = z.object({
title: z.string(),
kind: z.string(),
stage: z.string().optional(),
body: z.string().nullish(),
body: z.string(),
url: z.string().nullish(),
topic_id: PG_INT.nullish(),
pinned: z.boolean().nullish(),
Expand Down
5 changes: 5 additions & 0 deletions libs/shared/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ export const DISCORD_BOT_ADDRESS = '0xdiscordbot';
export const DEFAULT_NAME = 'Anonymous';

export const MAX_RECIPIENTS_PER_WORKFLOW_TRIGGER = 1_000;

// The maximum number of characters allowed in 'body' and 'text'
// columns of Threads, Comments, and version history models.
// Full content found by fetching from 'content_url'.
export const MAX_TRUNCATED_CONTENT_LENGTH = 2_000;

This file was deleted.

Loading

0 comments on commit 86c026b

Please sign in to comment.