Refactor validations
This commit is contained in:
@@ -6,8 +6,8 @@ import { useDrag, useDrop } from "react-dnd";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import { sortNavigationNodes } from "@shared/utils/collections";
|
import { sortNavigationNodes } from "@shared/utils/collections";
|
||||||
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import Collection from "~/models/Collection";
|
import Collection from "~/models/Collection";
|
||||||
import Document from "~/models/Document";
|
import Document from "~/models/Document";
|
||||||
import Fade from "~/components/Fade";
|
import Fade from "~/components/Fade";
|
||||||
@@ -319,7 +319,7 @@ function InnerDocumentLink(
|
|||||||
onSubmit={handleTitleChange}
|
onSubmit={handleTitleChange}
|
||||||
onEditing={handleTitleEditing}
|
onEditing={handleTitleEditing}
|
||||||
canUpdate={canUpdate}
|
canUpdate={canUpdate}
|
||||||
maxLength={MAX_TITLE_LENGTH}
|
maxLength={DocumentValidation.maxTitleLength}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
isActive={(match, location: Location<{ starred?: boolean }>) =>
|
isActive={(match, location: Location<{ starred?: boolean }>) =>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
import { CollectionValidation } from "@shared/validations";
|
||||||
import Button from "~/components/Button";
|
import Button from "~/components/Button";
|
||||||
import Flex from "~/components/Flex";
|
import Flex from "~/components/Flex";
|
||||||
import IconPicker from "~/components/IconPicker";
|
import IconPicker from "~/components/IconPicker";
|
||||||
@@ -94,7 +94,7 @@ const CollectionEdit = ({ collectionId, onSubmit }: Props) => {
|
|||||||
type="text"
|
type="text"
|
||||||
label={t("Name")}
|
label={t("Name")}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
maxLength={MAX_TITLE_LENGTH}
|
maxLength={CollectionValidation.maxNameLength}
|
||||||
value={name}
|
value={name}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { observable } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { withTranslation, Trans, WithTranslation } from "react-i18next";
|
import { withTranslation, Trans, WithTranslation } from "react-i18next";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
import { CollectionValidation } from "@shared/validations";
|
||||||
import RootStore from "~/stores/RootStore";
|
import RootStore from "~/stores/RootStore";
|
||||||
import Collection from "~/models/Collection";
|
import Collection from "~/models/Collection";
|
||||||
import Button from "~/components/Button";
|
import Button from "~/components/Button";
|
||||||
@@ -128,7 +128,7 @@ class CollectionNew extends React.Component<Props> {
|
|||||||
type="text"
|
type="text"
|
||||||
label={t("Name")}
|
label={t("Name")}
|
||||||
onChange={this.handleNameChange}
|
onChange={this.handleNameChange}
|
||||||
maxLength={MAX_TITLE_LENGTH}
|
maxLength={CollectionValidation.maxNameLength}
|
||||||
value={this.name}
|
value={this.name}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import { observer } from "mobx-react";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import breakpoint from "styled-components-breakpoint";
|
import breakpoint from "styled-components-breakpoint";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import { light } from "@shared/styles/theme";
|
import { light } from "@shared/styles/theme";
|
||||||
import {
|
import {
|
||||||
getCurrentDateAsString,
|
getCurrentDateAsString,
|
||||||
getCurrentDateTimeAsString,
|
getCurrentDateTimeAsString,
|
||||||
getCurrentTimeAsString,
|
getCurrentTimeAsString,
|
||||||
} from "@shared/utils/date";
|
} from "@shared/utils/date";
|
||||||
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import Document from "~/models/Document";
|
import Document from "~/models/Document";
|
||||||
import ContentEditable, { RefHandle } from "~/components/ContentEditable";
|
import ContentEditable, { RefHandle } from "~/components/ContentEditable";
|
||||||
import Star, { AnimatedStar } from "~/components/Star";
|
import Star, { AnimatedStar } from "~/components/Star";
|
||||||
@@ -132,7 +132,7 @@ const EditableTitle = React.forwardRef(
|
|||||||
$emojiWidth={emojiWidth}
|
$emojiWidth={emojiWidth}
|
||||||
$isStarred={document.isStarred}
|
$isStarred={document.isStarred}
|
||||||
autoFocus={!value}
|
autoFocus={!value}
|
||||||
maxLength={MAX_TITLE_LENGTH}
|
maxLength={DocumentValidation.maxTitleLength}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
dir="auto"
|
dir="auto"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import path from "path";
|
|||||||
import invariant from "invariant";
|
import invariant from "invariant";
|
||||||
import { find, orderBy, filter, compact, omitBy } from "lodash";
|
import { find, orderBy, filter, compact, omitBy } from "lodash";
|
||||||
import { observable, action, computed, runInAction } from "mobx";
|
import { observable, action, computed, runInAction } from "mobx";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import { DateFilter } from "@shared/types";
|
import { DateFilter } from "@shared/types";
|
||||||
import { subtractDate } from "@shared/utils/date";
|
import { subtractDate } from "@shared/utils/date";
|
||||||
import naturalSort from "@shared/utils/naturalSort";
|
import naturalSort from "@shared/utils/naturalSort";
|
||||||
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import BaseStore from "~/stores/BaseStore";
|
import BaseStore from "~/stores/BaseStore";
|
||||||
import RootStore from "~/stores/RootStore";
|
import RootStore from "~/stores/RootStore";
|
||||||
import Document from "~/models/Document";
|
import Document from "~/models/Document";
|
||||||
@@ -553,7 +553,7 @@ export default class DocumentsStore extends BaseStore<Document> {
|
|||||||
template: document.template,
|
template: document.template,
|
||||||
title: `${document.title.slice(
|
title: `${document.title.slice(
|
||||||
0,
|
0,
|
||||||
MAX_TITLE_LENGTH - append.length
|
DocumentValidation.maxTitleLength - append.length
|
||||||
)}${append}`,
|
)}${append}`,
|
||||||
text: document.text,
|
text: document.text,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import mammoth from "mammoth";
|
|||||||
import quotedPrintable from "quoted-printable";
|
import quotedPrintable from "quoted-printable";
|
||||||
import { Transaction } from "sequelize";
|
import { Transaction } from "sequelize";
|
||||||
import utf8 from "utf8";
|
import utf8 from "utf8";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import parseTitle from "@shared/utils/parseTitle";
|
import parseTitle from "@shared/utils/parseTitle";
|
||||||
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import { APM } from "@server/logging/tracing";
|
import { APM } from "@server/logging/tracing";
|
||||||
import { User } from "@server/models";
|
import { User } from "@server/models";
|
||||||
import dataURItoBuffer from "@server/utils/dataURItoBuffer";
|
import dataURItoBuffer from "@server/utils/dataURItoBuffer";
|
||||||
@@ -221,7 +221,7 @@ async function documentImporter({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// It's better to truncate particularly long titles than fail the import
|
// It's better to truncate particularly long titles than fail the import
|
||||||
title = truncate(title, { length: MAX_TITLE_LENGTH });
|
title = truncate(title, { length: DocumentValidation.maxTitleLength });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text,
|
text,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import fractionalIndex from "fractional-index";
|
import fractionalIndex from "fractional-index";
|
||||||
import { Sequelize, Op, WhereOptions } from "sequelize";
|
import { Sequelize, Op, WhereOptions } from "sequelize";
|
||||||
|
import { PinValidation } from "@shared/validations";
|
||||||
import { sequelize } from "@server/database/sequelize";
|
import { sequelize } from "@server/database/sequelize";
|
||||||
import { ValidationError } from "@server/errors";
|
import { ValidationError } from "@server/errors";
|
||||||
import { Pin, User, Event } from "@server/models";
|
import { Pin, User, Event } from "@server/models";
|
||||||
|
|
||||||
const MAX_PINS = 8;
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/** The user creating the pin */
|
/** The user creating the pin */
|
||||||
user: User;
|
user: User;
|
||||||
@@ -40,8 +39,10 @@ export default async function pinCreator({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const count = await Pin.count({ where });
|
const count = await Pin.count({ where });
|
||||||
if (count >= MAX_PINS) {
|
if (count >= PinValidation.max) {
|
||||||
throw ValidationError(`You cannot pin more than ${MAX_PINS} documents`);
|
throw ValidationError(
|
||||||
|
`You cannot pin more than ${PinValidation.max} documents`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!index) {
|
if (!index) {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import {
|
|||||||
Length as SimpleLength,
|
Length as SimpleLength,
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
import isUUID from "validator/lib/isUUID";
|
import isUUID from "validator/lib/isUUID";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import { sortNavigationNodes } from "@shared/utils/collections";
|
import { sortNavigationNodes } from "@shared/utils/collections";
|
||||||
import { SLUG_URL_REGEX } from "@shared/utils/urlHelpers";
|
import { SLUG_URL_REGEX } from "@shared/utils/urlHelpers";
|
||||||
import { CollectionValidation } from "@shared/validations";
|
import { CollectionValidation } from "@shared/validations";
|
||||||
@@ -144,8 +143,8 @@ class Collection extends ParanoidModel {
|
|||||||
|
|
||||||
@NotContainsUrl
|
@NotContainsUrl
|
||||||
@Length({
|
@Length({
|
||||||
max: MAX_TITLE_LENGTH,
|
max: CollectionValidation.maxNameLength,
|
||||||
msg: `name must be ${MAX_TITLE_LENGTH} characters or less`,
|
msg: `name must be ${CollectionValidation.maxNameLength} characters or less`,
|
||||||
})
|
})
|
||||||
@Column
|
@Column
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ import {
|
|||||||
import MarkdownSerializer from "slate-md-serializer";
|
import MarkdownSerializer from "slate-md-serializer";
|
||||||
import isUUID from "validator/lib/isUUID";
|
import isUUID from "validator/lib/isUUID";
|
||||||
import * as Y from "yjs";
|
import * as Y from "yjs";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
|
||||||
import { DateFilter } from "@shared/types";
|
import { DateFilter } from "@shared/types";
|
||||||
import getTasks from "@shared/utils/getTasks";
|
import getTasks from "@shared/utils/getTasks";
|
||||||
import parseTitle from "@shared/utils/parseTitle";
|
import parseTitle from "@shared/utils/parseTitle";
|
||||||
import unescape from "@shared/utils/unescape";
|
import unescape from "@shared/utils/unescape";
|
||||||
import { SLUG_URL_REGEX } from "@shared/utils/urlHelpers";
|
import { SLUG_URL_REGEX } from "@shared/utils/urlHelpers";
|
||||||
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import { parser } from "@server/editor";
|
import { parser } from "@server/editor";
|
||||||
import slugify from "@server/utils/slugify";
|
import slugify from "@server/utils/slugify";
|
||||||
import Backlink from "./Backlink";
|
import Backlink from "./Backlink";
|
||||||
@@ -196,8 +196,8 @@ class Document extends ParanoidModel {
|
|||||||
urlId: string;
|
urlId: string;
|
||||||
|
|
||||||
@Length({
|
@Length({
|
||||||
max: MAX_TITLE_LENGTH,
|
max: DocumentValidation.maxTitleLength,
|
||||||
msg: `Document title must be ${MAX_TITLE_LENGTH} characters or less`,
|
msg: `Document title must be ${DocumentValidation.maxTitleLength} characters or less`,
|
||||||
})
|
})
|
||||||
@Column
|
@Column
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
Length as SimpleLength,
|
Length as SimpleLength,
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
import MarkdownSerializer from "slate-md-serializer";
|
import MarkdownSerializer from "slate-md-serializer";
|
||||||
import { MAX_TITLE_LENGTH } from "@shared/constants";
|
import { DocumentValidation } from "@shared/validations";
|
||||||
import Document from "./Document";
|
import Document from "./Document";
|
||||||
import User from "./User";
|
import User from "./User";
|
||||||
import IdModel from "./base/IdModel";
|
import IdModel from "./base/IdModel";
|
||||||
@@ -43,8 +43,8 @@ class Revision extends IdModel {
|
|||||||
editorVersion: string;
|
editorVersion: string;
|
||||||
|
|
||||||
@Length({
|
@Length({
|
||||||
max: MAX_TITLE_LENGTH,
|
max: DocumentValidation.maxTitleLength,
|
||||||
msg: `Revision title must be ${MAX_TITLE_LENGTH} characters or less`,
|
msg: `Revision title must be ${DocumentValidation.maxTitleLength} characters or less`,
|
||||||
})
|
})
|
||||||
@Column
|
@Column
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
BeforeValidate,
|
BeforeValidate,
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
} from "sequelize-typescript";
|
} from "sequelize-typescript";
|
||||||
import { MAX_TEAM_DOMAINS } from "@shared/constants";
|
import { TeamValidation } from "@shared/validations";
|
||||||
import { ValidationError } from "@server/errors";
|
import { ValidationError } from "@server/errors";
|
||||||
import Team from "./Team";
|
import Team from "./Team";
|
||||||
import User from "./User";
|
import User from "./User";
|
||||||
@@ -59,9 +59,9 @@ class TeamDomain extends IdModel {
|
|||||||
const count = await this.count({
|
const count = await this.count({
|
||||||
where: { teamId: model.teamId },
|
where: { teamId: model.teamId },
|
||||||
});
|
});
|
||||||
if (count >= MAX_TEAM_DOMAINS) {
|
if (count >= TeamValidation.maxDomains) {
|
||||||
throw ValidationError(
|
throw ValidationError(
|
||||||
`You have reached the limit of ${MAX_TEAM_DOMAINS} domains`
|
`You have reached the limit of ${TeamValidation.maxDomains} domains`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
export const USER_PRESENCE_INTERVAL = 5000;
|
export const USER_PRESENCE_INTERVAL = 5000;
|
||||||
|
|
||||||
export const MAX_AVATAR_DISPLAY = 6;
|
export const MAX_AVATAR_DISPLAY = 6;
|
||||||
|
|
||||||
export const MAX_TITLE_LENGTH = 100;
|
|
||||||
|
|
||||||
export const MAX_TEAM_DOMAINS = 10;
|
|
||||||
|
|||||||
@@ -1,4 +1,22 @@
|
|||||||
export const CollectionValidation = {
|
export const CollectionValidation = {
|
||||||
/* The maximum length of the collection description */
|
/** The maximum length of the collection description */
|
||||||
maxDescriptionLength: 1000,
|
maxDescriptionLength: 1000,
|
||||||
|
|
||||||
|
/** The maximum length of the collection name */
|
||||||
|
maxNameLength: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DocumentValidation = {
|
||||||
|
/** The maximum length of the document title */
|
||||||
|
maxTitleLength: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PinValidation = {
|
||||||
|
/** The maximum number of pinned documents on an individual collection or home screen */
|
||||||
|
max: 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TeamValidation = {
|
||||||
|
/** The maximum number of domains per team */
|
||||||
|
maxDomains: 10,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user