mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cde0edfc67 | |||
| e566926720 | |||
| ae4a7d7166 | |||
| ebb92cfa88 | |||
| 33bd2950be |
@@ -36,8 +36,6 @@ class Attachment extends IdModel<
|
||||
InferAttributes<Attachment>,
|
||||
Partial<InferCreationAttributes<Attachment>>
|
||||
> {
|
||||
static eventNamespace = "attachments";
|
||||
|
||||
@Length({
|
||||
max: 4096,
|
||||
msg: "key must be 4096 characters or less",
|
||||
|
||||
@@ -166,8 +166,6 @@ class Collection extends ParanoidModel<
|
||||
InferAttributes<Collection>,
|
||||
Partial<InferCreationAttributes<Collection>>
|
||||
> {
|
||||
static eventNamespace = "collections";
|
||||
|
||||
@SimpleLength({
|
||||
min: 10,
|
||||
max: 10,
|
||||
|
||||
@@ -42,8 +42,6 @@ class Comment extends ParanoidModel<
|
||||
InferAttributes<Comment>,
|
||||
Partial<InferCreationAttributes<Comment>>
|
||||
> {
|
||||
static eventNamespace = "comments";
|
||||
|
||||
@TextLength({
|
||||
max: CommentValidation.maxLength,
|
||||
msg: `Comment must be less than ${CommentValidation.maxLength} characters`,
|
||||
|
||||
@@ -254,8 +254,6 @@ class Document extends ArchivableModel<
|
||||
InferAttributes<Document>,
|
||||
Partial<InferCreationAttributes<Document>>
|
||||
> {
|
||||
static eventNamespace = "documents";
|
||||
|
||||
@SimpleLength({
|
||||
min: 10,
|
||||
max: 10,
|
||||
|
||||
@@ -60,8 +60,6 @@ class Group extends ParanoidModel<
|
||||
InferAttributes<Group>,
|
||||
Partial<InferCreationAttributes<Group>>
|
||||
> {
|
||||
static eventNamespace = "groups";
|
||||
|
||||
@Length({ min: 0, max: 255, msg: "name must be be 255 characters or less" })
|
||||
@NotContainsUrl
|
||||
@Column
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
AfterDestroy,
|
||||
} from "sequelize-typescript";
|
||||
import { CollectionPermission, DocumentPermission } from "@shared/types";
|
||||
import { APIContext } from "@server/types";
|
||||
import Collection from "./Collection";
|
||||
import Document from "./Document";
|
||||
import Group from "./Group";
|
||||
@@ -211,20 +212,12 @@ class GroupMembership extends ParanoidModel<
|
||||
@AfterCreate
|
||||
static async publishAddGroupEventAfterCreate(
|
||||
model: GroupMembership,
|
||||
context: HookContext
|
||||
context: APIContext["context"]
|
||||
) {
|
||||
const data = { membershipId: model.id, isNew: true };
|
||||
|
||||
const ctxWithData = {
|
||||
...context,
|
||||
event: { ...context.event, data },
|
||||
} as HookContext;
|
||||
|
||||
if (model.collectionId) {
|
||||
await Collection.insertEvent("add_group", model, ctxWithData);
|
||||
} else {
|
||||
await Document.insertEvent("add_group", model, ctxWithData);
|
||||
}
|
||||
await model.insertEvent(context, "add_group", {
|
||||
membershipId: model.id,
|
||||
isNew: true,
|
||||
});
|
||||
}
|
||||
|
||||
@AfterUpdate
|
||||
@@ -257,20 +250,12 @@ class GroupMembership extends ParanoidModel<
|
||||
@AfterUpdate
|
||||
static async publishAddGroupEventAfterUpdate(
|
||||
model: GroupMembership,
|
||||
context: HookContext
|
||||
context: APIContext["context"]
|
||||
) {
|
||||
const data = { membershipId: model.id, isNew: false };
|
||||
|
||||
const ctxWithData = {
|
||||
...context,
|
||||
event: { ...context.event, data },
|
||||
} as HookContext;
|
||||
|
||||
if (model.collectionId) {
|
||||
await Collection.insertEvent("add_group", model, ctxWithData);
|
||||
} else {
|
||||
await Document.insertEvent("add_group", model, ctxWithData);
|
||||
}
|
||||
await model.insertEvent(context, "add_group", {
|
||||
membershipId: model.id,
|
||||
isNew: false,
|
||||
});
|
||||
}
|
||||
|
||||
@AfterDestroy
|
||||
@@ -295,20 +280,11 @@ class GroupMembership extends ParanoidModel<
|
||||
@AfterDestroy
|
||||
static async publishRemoveGroupEvent(
|
||||
model: GroupMembership,
|
||||
context: HookContext
|
||||
context: APIContext["context"]
|
||||
) {
|
||||
const data = { membershipId: model.id };
|
||||
|
||||
const ctxWithData = {
|
||||
...context,
|
||||
event: { ...context.event, data },
|
||||
} as HookContext;
|
||||
|
||||
if (model.collectionId) {
|
||||
await Collection.insertEvent("remove_group", model, ctxWithData);
|
||||
} else {
|
||||
await Document.insertEvent("remove_group", model, ctxWithData);
|
||||
}
|
||||
await model.insertEvent(context, "remove_group", {
|
||||
membershipId: model.id,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,6 +348,23 @@ class GroupMembership extends ParanoidModel<
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async insertEvent(
|
||||
ctx: APIContext["context"],
|
||||
name: string,
|
||||
data: Record<string, unknown>
|
||||
) {
|
||||
const hookContext = {
|
||||
...ctx,
|
||||
event: { name, data, create: true },
|
||||
} as HookContext;
|
||||
|
||||
if (this.collectionId) {
|
||||
await Collection.insertEvent(name, this, hookContext);
|
||||
} else {
|
||||
await Document.insertEvent(name, this, hookContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupMembership;
|
||||
|
||||
@@ -7,12 +7,10 @@ import {
|
||||
Table,
|
||||
DataType,
|
||||
Scopes,
|
||||
AfterCreate,
|
||||
AfterDestroy,
|
||||
} from "sequelize-typescript";
|
||||
import Group from "./Group";
|
||||
import User from "./User";
|
||||
import Model, { type HookContext } from "./base/Model";
|
||||
import Model from "./base/Model";
|
||||
import Fix from "./decorators/Fix";
|
||||
|
||||
@DefaultScope(() => ({
|
||||
@@ -44,6 +42,8 @@ class GroupUser extends Model<
|
||||
InferAttributes<GroupUser>,
|
||||
Partial<InferCreationAttributes<GroupUser>>
|
||||
> {
|
||||
static eventNamespace = "groups";
|
||||
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
@@ -68,24 +68,6 @@ class GroupUser extends Model<
|
||||
get modelId() {
|
||||
return this.groupId;
|
||||
}
|
||||
|
||||
// hooks
|
||||
|
||||
@AfterCreate
|
||||
public static async publishAddUserEvent(
|
||||
model: GroupUser,
|
||||
context: HookContext
|
||||
) {
|
||||
await Group.insertEvent("add_user", model, context);
|
||||
}
|
||||
|
||||
@AfterDestroy
|
||||
public static async publishRemoveUserEvent(
|
||||
model: GroupUser,
|
||||
context: HookContext
|
||||
) {
|
||||
await Group.insertEvent("remove_user", model, context);
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupUser;
|
||||
|
||||
@@ -20,8 +20,6 @@ class Pin extends IdModel<
|
||||
InferAttributes<Pin>,
|
||||
Partial<InferCreationAttributes<Pin>>
|
||||
> {
|
||||
static eventNamespace = "pins";
|
||||
|
||||
@Length({
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
|
||||
@@ -18,10 +18,10 @@ import {
|
||||
Table,
|
||||
} from "sequelize-typescript";
|
||||
import { createContext } from "@server/context";
|
||||
import { APIContext } from "@server/types";
|
||||
import Comment from "./Comment";
|
||||
import User from "./User";
|
||||
import IdModel from "./base/IdModel";
|
||||
import { type HookContext } from "./base/Model";
|
||||
import Fix from "./decorators/Fix";
|
||||
import Length from "./validators/Length";
|
||||
|
||||
@@ -57,7 +57,7 @@ class Reaction extends IdModel<
|
||||
@AfterCreate
|
||||
public static async addReactionToCommentCache(
|
||||
model: Reaction,
|
||||
ctx: HookContext &
|
||||
ctx: APIContext["context"] &
|
||||
FindOrCreateOptions<Attributes<Reaction>, CreationAttributes<Reaction>>
|
||||
) {
|
||||
const { transaction } = ctx;
|
||||
@@ -109,7 +109,7 @@ class Reaction extends IdModel<
|
||||
@AfterDestroy
|
||||
public static async removeReactionFromCommentCache(
|
||||
model: Reaction,
|
||||
ctx: HookContext & InstanceDestroyOptions
|
||||
ctx: APIContext["context"] & InstanceDestroyOptions
|
||||
) {
|
||||
const { transaction } = ctx;
|
||||
|
||||
|
||||
@@ -83,8 +83,6 @@ class Share extends IdModel<
|
||||
InferAttributes<Share>,
|
||||
Partial<InferCreationAttributes<Share>>
|
||||
> {
|
||||
static eventNamespace = "shares";
|
||||
|
||||
@Column
|
||||
published: boolean;
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ class Star extends IdModel<
|
||||
InferAttributes<Star>,
|
||||
Partial<InferCreationAttributes<Star>>
|
||||
> {
|
||||
static eventNamespace = "stars";
|
||||
|
||||
@Length({
|
||||
max: 256,
|
||||
msg: `index must be 256 characters or less`,
|
||||
|
||||
@@ -28,8 +28,6 @@ class Subscription extends ParanoidModel<
|
||||
InferAttributes<Subscription>,
|
||||
Partial<InferCreationAttributes<Subscription>>
|
||||
> {
|
||||
static eventNamespace = "subscriptions";
|
||||
|
||||
@BelongsTo(() => User, "userId")
|
||||
user: User;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
AfterRestore,
|
||||
AfterUpdate,
|
||||
AfterUpsert,
|
||||
BeforeCreate,
|
||||
BeforeSave,
|
||||
Model as SequelizeModel,
|
||||
} from "sequelize-typescript";
|
||||
import Logger from "@server/logging/Logger";
|
||||
@@ -47,8 +47,7 @@ class Model<
|
||||
TCreationAttributes extends {} = TModelAttributes
|
||||
> extends SequelizeModel<TModelAttributes, TCreationAttributes> {
|
||||
/**
|
||||
* The namespace to use for events, if none is provided an event will not be created
|
||||
* during the migration period. In the future this may default to the table name.
|
||||
* The namespace to use for events - defaults to the table name if none is provided.
|
||||
*/
|
||||
static eventNamespace: string | undefined;
|
||||
|
||||
@@ -67,7 +66,6 @@ class Model<
|
||||
create: true,
|
||||
},
|
||||
};
|
||||
this.cacheChangeset();
|
||||
return this.save({ ...options, ...hookContext });
|
||||
}
|
||||
|
||||
@@ -87,7 +85,6 @@ class Model<
|
||||
},
|
||||
};
|
||||
this.set(keys);
|
||||
this.cacheChangeset();
|
||||
return this.save(hookContext);
|
||||
}
|
||||
|
||||
@@ -162,8 +159,8 @@ class Model<
|
||||
return this.create(values, hookContext);
|
||||
}
|
||||
|
||||
@BeforeCreate
|
||||
static async beforeCreateEvent<T extends Model>(model: T) {
|
||||
@BeforeSave
|
||||
static async beforeSaveEvent<T extends Model>(model: T) {
|
||||
model.cacheChangeset();
|
||||
}
|
||||
|
||||
@@ -219,11 +216,10 @@ class Model<
|
||||
model: T,
|
||||
context: HookContext
|
||||
) {
|
||||
const namespace = this.eventNamespace;
|
||||
const namespace = this.eventNamespace ?? this.tableName;
|
||||
const models = this.sequelize!.models;
|
||||
|
||||
// If no namespace is defined, don't create an event
|
||||
if (!namespace || !context.event?.create) {
|
||||
if (!context.event?.create) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,24 +211,22 @@ router.post(
|
||||
authorize(user, "update", collection);
|
||||
authorize(user, "read", group);
|
||||
|
||||
const [membership, created] = await GroupMembership.findOrCreateWithCtx(
|
||||
ctx,
|
||||
{
|
||||
where: {
|
||||
collectionId: id,
|
||||
groupId,
|
||||
},
|
||||
defaults: {
|
||||
permission,
|
||||
createdById: user.id,
|
||||
},
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
}
|
||||
);
|
||||
const [membership, created] = await GroupMembership.findOrCreate({
|
||||
where: {
|
||||
collectionId: id,
|
||||
groupId,
|
||||
},
|
||||
defaults: {
|
||||
permission,
|
||||
createdById: user.id,
|
||||
},
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
...ctx.context,
|
||||
});
|
||||
|
||||
if (!created) {
|
||||
membership.permission = permission;
|
||||
await membership.saveWithCtx(ctx);
|
||||
await membership.save(ctx.context);
|
||||
}
|
||||
|
||||
const groupMemberships = [presentGroupMembership(membership)];
|
||||
@@ -273,7 +271,7 @@ router.post(
|
||||
ctx.throw(400, "This Group is not a part of the collection");
|
||||
}
|
||||
|
||||
await membership.destroyWithCtx(ctx);
|
||||
await membership.destroy(ctx.context);
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
|
||||
@@ -375,12 +375,13 @@ router.post(
|
||||
authorize(user, "comment", document);
|
||||
authorize(user, "addReaction", comment);
|
||||
|
||||
await Reaction.findOrCreateWithCtx(ctx, {
|
||||
await Reaction.findOrCreate({
|
||||
where: {
|
||||
emoji,
|
||||
userId: user.id,
|
||||
commentId: id,
|
||||
},
|
||||
...ctx.context,
|
||||
});
|
||||
|
||||
ctx.body = {
|
||||
@@ -423,7 +424,7 @@ router.post(
|
||||
});
|
||||
authorize(user, "delete", reaction);
|
||||
|
||||
await reaction.destroyWithCtx(ctx);
|
||||
await reaction.destroy(ctx.context);
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
|
||||
@@ -1839,20 +1839,18 @@ router.post(
|
||||
authorize(user, "update", document);
|
||||
authorize(user, "read", group);
|
||||
|
||||
const [membership, created] = await GroupMembership.findOrCreateWithCtx(
|
||||
ctx,
|
||||
{
|
||||
where: {
|
||||
documentId: id,
|
||||
groupId,
|
||||
},
|
||||
defaults: {
|
||||
permission: permission || user.defaultDocumentPermission,
|
||||
createdById: user.id,
|
||||
},
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
}
|
||||
);
|
||||
const [membership, created] = await GroupMembership.findOrCreate({
|
||||
where: {
|
||||
documentId: id,
|
||||
groupId,
|
||||
},
|
||||
defaults: {
|
||||
permission: permission || user.defaultDocumentPermission,
|
||||
createdById: user.id,
|
||||
},
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
...ctx.context,
|
||||
});
|
||||
|
||||
if (!created && permission) {
|
||||
membership.permission = permission;
|
||||
@@ -1860,7 +1858,7 @@ router.post(
|
||||
// disconnect from the source if the permission is manually updated
|
||||
membership.sourceId = null;
|
||||
|
||||
await membership.saveWithCtx(ctx);
|
||||
await membership.save(ctx.context);
|
||||
}
|
||||
|
||||
ctx.body = {
|
||||
@@ -1905,7 +1903,7 @@ router.post(
|
||||
rejectOnEmpty: true,
|
||||
});
|
||||
|
||||
await membership.destroyWithCtx(ctx);
|
||||
await membership.destroy(ctx.context);
|
||||
|
||||
ctx.body = {
|
||||
success: true,
|
||||
|
||||
@@ -261,15 +261,19 @@ router.post(
|
||||
const group = await Group.findByPk(id, { transaction });
|
||||
authorize(actor, "update", group);
|
||||
|
||||
const [groupUser] = await GroupUser.findOrCreateWithCtx(ctx, {
|
||||
where: {
|
||||
groupId: group.id,
|
||||
userId: user.id,
|
||||
const [groupUser] = await GroupUser.findOrCreateWithCtx(
|
||||
ctx,
|
||||
{
|
||||
where: {
|
||||
groupId: group.id,
|
||||
userId: user.id,
|
||||
},
|
||||
defaults: {
|
||||
createdById: actor.id,
|
||||
},
|
||||
},
|
||||
defaults: {
|
||||
createdById: actor.id,
|
||||
},
|
||||
});
|
||||
{ name: "add_user" }
|
||||
);
|
||||
|
||||
groupUser.user = user;
|
||||
|
||||
@@ -308,7 +312,7 @@ router.post(
|
||||
lock: transaction.LOCK.UPDATE,
|
||||
});
|
||||
|
||||
await groupUser?.destroyWithCtx(ctx);
|
||||
await groupUser?.destroyWithCtx(ctx, { name: "remove_user" });
|
||||
|
||||
ctx.body = {
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user