chore: Synchronizing refactor and small fixes from enterprise codebase (#3634)
* chore: Syncronizing refactor and small fixes from enterprise codebase * fix
This commit is contained in:
@@ -38,6 +38,13 @@ const RealInput = styled.input<{ hasIcon?: boolean }>`
|
||||
color: ${(props) => props.theme.placeholder};
|
||||
}
|
||||
|
||||
&:-webkit-autofill,
|
||||
&:-webkit-autofill:hover,
|
||||
&:-webkit-autofill:focus {
|
||||
-webkit-box-shadow: 0 0 0px 1000px ${(props) => props.theme.background}
|
||||
inset;
|
||||
}
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
@@ -97,7 +104,7 @@ export const LabelText = styled.div`
|
||||
display: inline-block;
|
||||
`;
|
||||
|
||||
export type Props = React.HTMLAttributes<HTMLInputElement> & {
|
||||
export type Props = Omit<React.HTMLAttributes<HTMLInputElement>, "onChange"> & {
|
||||
type?: "text" | "email" | "checkbox" | "search" | "textarea";
|
||||
value?: string;
|
||||
label?: string;
|
||||
@@ -108,6 +115,7 @@ export type Props = React.HTMLAttributes<HTMLInputElement> & {
|
||||
margin?: string | number;
|
||||
icon?: React.ReactNode;
|
||||
name?: string;
|
||||
pattern?: string;
|
||||
minLength?: number;
|
||||
maxLength?: number;
|
||||
autoFocus?: boolean;
|
||||
|
||||
@@ -37,7 +37,7 @@ async function teamPermanentDeleter(team: Team) {
|
||||
|
||||
try {
|
||||
transaction = await sequelize.transaction();
|
||||
await Attachment.findAllInBatches(
|
||||
await Attachment.findAllInBatches<Attachment>(
|
||||
{
|
||||
where: {
|
||||
teamId,
|
||||
@@ -62,7 +62,7 @@ async function teamPermanentDeleter(team: Team) {
|
||||
}
|
||||
);
|
||||
// Destroy user-relation models
|
||||
await User.findAllInBatches(
|
||||
await User.findAllInBatches<User>(
|
||||
{
|
||||
attributes: ["id"],
|
||||
where: {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import path from "path";
|
||||
import { FindOptions } from "sequelize";
|
||||
import {
|
||||
BeforeDestroy,
|
||||
BelongsTo,
|
||||
@@ -14,12 +13,12 @@ import { publicS3Endpoint, deleteFromS3, getFileByKey } from "@server/utils/s3";
|
||||
import Document from "./Document";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "attachments", modelName: "attachment" })
|
||||
@Fix
|
||||
class Attachment extends BaseModel {
|
||||
class Attachment extends IdModel {
|
||||
@Column
|
||||
key: string;
|
||||
|
||||
@@ -92,28 +91,6 @@ class Attachment extends BaseModel {
|
||||
@ForeignKey(() => User)
|
||||
@Column(DataType.UUID)
|
||||
userId: string;
|
||||
|
||||
static async findAllInBatches(
|
||||
query: FindOptions<Attachment>,
|
||||
callback: (
|
||||
attachments: Array<Attachment>,
|
||||
query: FindOptions<Attachment>
|
||||
) => Promise<void>
|
||||
) {
|
||||
if (!query.offset) {
|
||||
query.offset = 0;
|
||||
}
|
||||
if (!query.limit) {
|
||||
query.limit = 10;
|
||||
}
|
||||
let results;
|
||||
|
||||
do {
|
||||
results = await this.findAll(query);
|
||||
await callback(results, query);
|
||||
query.offset += query.limit;
|
||||
} while (results.length >= query.limit);
|
||||
}
|
||||
}
|
||||
|
||||
export default Attachment;
|
||||
|
||||
@@ -7,12 +7,12 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import Document from "./Document";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "backlinks", modelName: "backlink" })
|
||||
@Fix
|
||||
class Backlink extends BaseModel {
|
||||
class Backlink extends IdModel {
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -4,18 +4,18 @@ import {
|
||||
Default,
|
||||
ForeignKey,
|
||||
IsIn,
|
||||
Model,
|
||||
Table,
|
||||
DataType,
|
||||
} from "sequelize-typescript";
|
||||
import Collection from "./Collection";
|
||||
import Group from "./Group";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "collection_groups", modelName: "collection_group" })
|
||||
@Fix
|
||||
class CollectionGroup extends Model {
|
||||
class CollectionGroup extends BaseModel {
|
||||
@Default("read_write")
|
||||
@IsIn([["read", "read_write", "maintainer"]])
|
||||
@Column
|
||||
|
||||
@@ -6,15 +6,15 @@ import {
|
||||
IsIn,
|
||||
Table,
|
||||
DataType,
|
||||
Model,
|
||||
} from "sequelize-typescript";
|
||||
import Collection from "./Collection";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "collection_users", modelName: "collection_user" })
|
||||
@Fix
|
||||
class CollectionUser extends Model {
|
||||
class CollectionUser extends BaseModel {
|
||||
@Default("read_write")
|
||||
@IsIn([["read", "read_write", "maintainer"]])
|
||||
@Column
|
||||
|
||||
@@ -15,12 +15,12 @@ import Collection from "./Collection";
|
||||
import Document from "./Document";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "events", modelName: "event" })
|
||||
@Fix
|
||||
class Event extends BaseModel {
|
||||
class Event extends IdModel {
|
||||
@IsUUID(4)
|
||||
@Column(DataType.UUID)
|
||||
modelId: string;
|
||||
|
||||
@@ -11,7 +11,7 @@ import { deleteFromS3, getFileByKey } from "@server/utils/s3";
|
||||
import Collection from "./Collection";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
export enum FileOperationType {
|
||||
@@ -48,7 +48,7 @@ export enum FileOperationState {
|
||||
}))
|
||||
@Table({ tableName: "file_operations", modelName: "file_operation" })
|
||||
@Fix
|
||||
class FileOperation extends BaseModel {
|
||||
class FileOperation extends IdModel {
|
||||
@Column(DataType.ENUM("import", "export"))
|
||||
type: FileOperationType;
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import Fix from "./decorators/Fix";
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
order: [["name", "ASC"]],
|
||||
}))
|
||||
@Table({
|
||||
tableName: "groups",
|
||||
|
||||
@@ -5,10 +5,10 @@ import {
|
||||
Column,
|
||||
Table,
|
||||
DataType,
|
||||
Model,
|
||||
} from "sequelize-typescript";
|
||||
import Group from "./Group";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@DefaultScope(() => ({
|
||||
@@ -20,7 +20,7 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "group_users", modelName: "group_user", paranoid: true })
|
||||
@Fix
|
||||
class GroupUser extends Model {
|
||||
class GroupUser extends BaseModel {
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Collection from "./Collection";
|
||||
import IntegrationAuthentication from "./IntegrationAuthentication";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Scopes(() => ({
|
||||
@@ -26,7 +26,7 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "integrations", modelName: "integration" })
|
||||
@Fix
|
||||
class Integration extends BaseModel {
|
||||
class Integration extends IdModel {
|
||||
@Column
|
||||
type: string;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Encrypted, {
|
||||
getEncryptedColumn,
|
||||
setEncryptedColumn,
|
||||
@@ -16,7 +16,7 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "authentications", modelName: "authentication" })
|
||||
@Fix
|
||||
class IntegrationAuthentication extends BaseModel {
|
||||
class IntegrationAuthentication extends IdModel {
|
||||
@Column
|
||||
service: string;
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ import Collection from "./Collection";
|
||||
import Document from "./Document";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "pins", modelName: "pin" })
|
||||
@Fix
|
||||
class Pin extends BaseModel {
|
||||
class Pin extends IdModel {
|
||||
@Column
|
||||
index: string | null;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import MarkdownSerializer from "slate-md-serializer";
|
||||
import Document from "./Document";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
const serializer = new MarkdownSerializer();
|
||||
@@ -26,7 +26,7 @@ const serializer = new MarkdownSerializer();
|
||||
}))
|
||||
@Table({ tableName: "revisions", modelName: "revision" })
|
||||
@Fix
|
||||
class Revision extends BaseModel {
|
||||
class Revision extends IdModel {
|
||||
@Column(DataType.SMALLINT)
|
||||
version: number;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import Collection from "./Collection";
|
||||
import Document from "./Document";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@DefaultScope(() => ({
|
||||
@@ -66,7 +66,7 @@ import Fix from "./decorators/Fix";
|
||||
}))
|
||||
@Table({ tableName: "shares", modelName: "share" })
|
||||
@Fix
|
||||
class Share extends BaseModel {
|
||||
class Share extends IdModel {
|
||||
@Column
|
||||
published: boolean;
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ import {
|
||||
import Collection from "./Collection";
|
||||
import Document from "./Document";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "stars", modelName: "star" })
|
||||
@Fix
|
||||
class Star extends BaseModel {
|
||||
class Star extends IdModel {
|
||||
@Column
|
||||
index: string | null;
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "team_domains", modelName: "team_domain" })
|
||||
@Fix
|
||||
class TeamDomain extends BaseModel {
|
||||
class TeamDomain extends IdModel {
|
||||
@NotEmpty
|
||||
@Column
|
||||
name: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import crypto from "crypto";
|
||||
import { addMinutes, subMinutes } from "date-fns";
|
||||
import JWT from "jsonwebtoken";
|
||||
import { Transaction, QueryTypes, FindOptions, Op } from "sequelize";
|
||||
import { Transaction, QueryTypes, Op } from "sequelize";
|
||||
import {
|
||||
Table,
|
||||
Column,
|
||||
@@ -536,25 +536,6 @@ class User extends ParanoidModel {
|
||||
suspended: parseInt(counts.suspendedCount),
|
||||
};
|
||||
};
|
||||
|
||||
static async findAllInBatches(
|
||||
query: FindOptions<User>,
|
||||
callback: (users: Array<User>, query: FindOptions<User>) => Promise<void>
|
||||
) {
|
||||
if (!query.offset) {
|
||||
query.offset = 0;
|
||||
}
|
||||
if (!query.limit) {
|
||||
query.limit = 10;
|
||||
}
|
||||
let results;
|
||||
|
||||
do {
|
||||
results = await this.findAll(query);
|
||||
await callback(results, query);
|
||||
query.offset += query.limit;
|
||||
} while (results.length >= query.limit);
|
||||
}
|
||||
}
|
||||
|
||||
export default User;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "sequelize-typescript";
|
||||
import AuthenticationProvider from "./AuthenticationProvider";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Encrypted, {
|
||||
getEncryptedColumn,
|
||||
setEncryptedColumn,
|
||||
@@ -17,7 +17,7 @@ import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "user_authentications", modelName: "user_authentication" })
|
||||
@Fix
|
||||
class UserAuthentication extends BaseModel {
|
||||
class UserAuthentication extends IdModel {
|
||||
@Column(DataType.ARRAY(DataType.STRING))
|
||||
scopes: string[];
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ import {
|
||||
import { USER_PRESENCE_INTERVAL } from "@shared/constants";
|
||||
import Document from "./Document";
|
||||
import User from "./User";
|
||||
import BaseModel from "./base/BaseModel";
|
||||
import IdModel from "./base/IdModel";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@Table({ tableName: "views", modelName: "view" })
|
||||
@Fix
|
||||
class View extends BaseModel {
|
||||
class View extends IdModel {
|
||||
@Column
|
||||
lastEditingAt: Date | null;
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import {
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
Column,
|
||||
PrimaryKey,
|
||||
IsUUID,
|
||||
DataType,
|
||||
Model,
|
||||
Default,
|
||||
} from "sequelize-typescript";
|
||||
import { FindOptions } from "sequelize";
|
||||
import { Model } from "sequelize-typescript";
|
||||
|
||||
class BaseModel extends Model {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
@Column(DataType.UUID)
|
||||
id: string;
|
||||
static async findAllInBatches<T extends BaseModel>(
|
||||
query: FindOptions<T>,
|
||||
callback: (results: Array<T>, query: FindOptions<T>) => Promise<void>
|
||||
) {
|
||||
if (!query.offset) {
|
||||
query.offset = 0;
|
||||
}
|
||||
if (!query.limit) {
|
||||
query.limit = 10;
|
||||
}
|
||||
let results;
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date;
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date;
|
||||
do {
|
||||
// @ts-expect-error this T
|
||||
results = await this.findAll<T>(query);
|
||||
await callback(results, query);
|
||||
query.offset += query.limit;
|
||||
} while (results.length >= query.limit);
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseModel;
|
||||
|
||||
26
server/models/base/IdModel.ts
Normal file
26
server/models/base/IdModel.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import {
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
Column,
|
||||
PrimaryKey,
|
||||
IsUUID,
|
||||
DataType,
|
||||
Default,
|
||||
} from "sequelize-typescript";
|
||||
import BaseModel from "./BaseModel";
|
||||
|
||||
class IdModel extends BaseModel {
|
||||
@IsUUID(4)
|
||||
@PrimaryKey
|
||||
@Default(DataType.UUIDV4)
|
||||
@Column(DataType.UUID)
|
||||
id: string;
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date;
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export default IdModel;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DeletedAt } from "sequelize-typescript";
|
||||
import BaseModel from "./BaseModel";
|
||||
import IdModel from "./IdModel";
|
||||
|
||||
class ParanoidModel extends BaseModel {
|
||||
class ParanoidModel extends IdModel {
|
||||
@DeletedAt
|
||||
deletedAt: Date | null;
|
||||
}
|
||||
|
||||
@@ -642,6 +642,7 @@ router.post("collections.update", auth(), async (ctx) => {
|
||||
if (privacyChanged || sharingChanged) {
|
||||
await collection.reload();
|
||||
const team = await Team.findByPk(user.teamId);
|
||||
invariant(team, "team not found");
|
||||
|
||||
if (
|
||||
collection.permission === null &&
|
||||
|
||||
Reference in New Issue
Block a user