fix: Add server-side validation of comment length

This commit is contained in:
Tom Moor
2023-06-29 22:41:57 -04:00
parent 4bec08ee05
commit 8957e86c12
4 changed files with 54 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
import { subSeconds } from "date-fns";
import { computed, observable } from "mobx";
import { now } from "mobx-utils";
import type { ProsemirrorData } from "@shared/types";
import User from "~/models/User";
import BaseModel from "./BaseModel";
import Field from "./decorators/Field";
@@ -22,7 +23,7 @@ class Comment extends BaseModel {
*/
@Field
@observable
data: Record<string, any>;
data: ProsemirrorData;
/**
* If this comment is a reply then the parent comment will be set, otherwise

View File

@@ -5,12 +5,16 @@ import {
Column,
Table,
Scopes,
Length,
DefaultScope,
} from "sequelize-typescript";
import type { ProsemirrorData } from "@shared/types";
import { CommentValidation } from "@shared/validations";
import Document from "./Document";
import User from "./User";
import ParanoidModel from "./base/ParanoidModel";
import Fix from "./decorators/Fix";
import TextLength from "./validators/TextLength";
@DefaultScope(() => ({
include: [
@@ -35,8 +39,16 @@ import Fix from "./decorators/Fix";
@Table({ tableName: "comments", modelName: "comment" })
@Fix
class Comment extends ParanoidModel {
@TextLength({
max: CommentValidation.maxLength,
msg: `Comment must be less than ${CommentValidation.maxLength} characters`,
})
@Length({
max: CommentValidation.maxLength * 10,
msg: `Comment data is too large`,
})
@Column(DataType.JSONB)
data: Record<string, any>;
data: ProsemirrorData;
// associations

View File

@@ -0,0 +1,36 @@
import { size } from "lodash";
import { Node } from "prosemirror-model";
import { addAttributeOptions } from "sequelize-typescript";
import { ProsemirrorData } from "@shared/types";
import ProsemirrorHelper from "@shared/utils/ProsemirrorHelper";
import { schema } from "@server/editor";
/**
* A decorator that validates the size of the text within a prosemirror data
* object, taking into account unicode characters of variable lengths.
*/
export default function TextLength({
msg,
min = 0,
max,
}: {
msg?: string;
min?: number;
max: number;
}): (target: any, propertyName: string) => void {
return (target: any, propertyName: string) =>
addAttributeOptions(target, propertyName, {
validate: {
validLength(value: ProsemirrorData) {
const text = ProsemirrorHelper.toPlainText(
Node.fromJSON(schema, value),
schema
);
if (size(text) > max || size(text) < min) {
throw new Error(msg);
}
},
},
});
}

View File

@@ -208,3 +208,6 @@ export const NotificationEventDefaults = {
[NotificationEventType.Features]: true,
[NotificationEventType.ExportCompleted]: true,
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ProsemirrorData = Record<string, any>;