fix: Add server-side validation of comment length
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
36
server/models/validators/TextLength.ts
Normal file
36
server/models/validators/TextLength.ts
Normal 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);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -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>;
|
||||
|
||||
Reference in New Issue
Block a user