mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
feat(server): page model (#9715)
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
export * from './feature';
|
||||
export * from './page';
|
||||
export * from './permission';
|
||||
|
||||
4
packages/backend/server/src/models/common/page.ts
Normal file
4
packages/backend/server/src/models/common/page.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum PublicPageMode {
|
||||
Page,
|
||||
Edgeless,
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { ModuleRef } from '@nestjs/core';
|
||||
|
||||
import { ApplyType } from '../base';
|
||||
import { FeatureModel } from './feature';
|
||||
import { PageModel } from './page';
|
||||
import { MODELS_SYMBOL } from './provider';
|
||||
import { SessionModel } from './session';
|
||||
import { UserModel } from './user';
|
||||
@@ -20,6 +21,7 @@ const MODELS = {
|
||||
verificationToken: VerificationTokenModel,
|
||||
feature: FeatureModel,
|
||||
workspace: WorkspaceModel,
|
||||
page: PageModel,
|
||||
};
|
||||
|
||||
type ModelsType = {
|
||||
@@ -72,6 +74,7 @@ const ModelsSymbolProvider: ExistingProvider = {
|
||||
export class ModelModules {}
|
||||
|
||||
export * from './feature';
|
||||
export * from './page';
|
||||
export * from './session';
|
||||
export * from './user';
|
||||
export * from './verification-token';
|
||||
|
||||
201
packages/backend/server/src/models/page.ts
Normal file
201
packages/backend/server/src/models/page.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
type WorkspacePage as Page,
|
||||
type WorkspacePageUserPermission as PageUserPermission,
|
||||
} from '@prisma/client';
|
||||
|
||||
import { BaseModel } from './base';
|
||||
import { Permission, PublicPageMode } from './common';
|
||||
|
||||
export type { Page };
|
||||
export type UpdatePageInput = {
|
||||
mode?: PublicPageMode;
|
||||
public?: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class PageModel extends BaseModel {
|
||||
// #region page
|
||||
|
||||
/**
|
||||
* Create or update the page.
|
||||
*/
|
||||
async upsert(workspaceId: string, pageId: string, data?: UpdatePageInput) {
|
||||
return await this.db.workspacePage.upsert({
|
||||
where: {
|
||||
workspaceId_pageId: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
...data,
|
||||
},
|
||||
create: {
|
||||
...data,
|
||||
workspaceId,
|
||||
pageId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page.
|
||||
* @param isPublic: if true, only return the public page. If false, only return the private page.
|
||||
* If not set, return public or private both.
|
||||
*/
|
||||
async get(workspaceId: string, pageId: string, isPublic?: boolean) {
|
||||
return await this.db.workspacePage.findUnique({
|
||||
where: {
|
||||
workspaceId_pageId: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
},
|
||||
public: isPublic,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the workspace public pages.
|
||||
*/
|
||||
async findPublics(workspaceId: string) {
|
||||
return await this.db.workspacePage.findMany({
|
||||
where: {
|
||||
workspaceId,
|
||||
public: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the workspace public pages count.
|
||||
*/
|
||||
async getPublicsCount(workspaceId: string) {
|
||||
return await this.db.workspacePage.count({
|
||||
where: {
|
||||
workspaceId,
|
||||
public: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region page member and permission
|
||||
|
||||
/**
|
||||
* Grant the page member with the given permission.
|
||||
*/
|
||||
async grantMember(
|
||||
workspaceId: string,
|
||||
pageId: string,
|
||||
userId: string,
|
||||
permission: Permission = Permission.Read
|
||||
): Promise<PageUserPermission> {
|
||||
let data = await this.db.workspacePageUserPermission.findUnique({
|
||||
where: {
|
||||
workspaceId_pageId_userId: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// If the user is already accepted and the new permission is owner, we need to revoke old owner
|
||||
if (!data || data.type !== permission) {
|
||||
return await this.db.$transaction(async tx => {
|
||||
if (data) {
|
||||
// Update the permission
|
||||
data = await tx.workspacePageUserPermission.update({
|
||||
where: {
|
||||
workspaceId_pageId_userId: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
userId,
|
||||
},
|
||||
},
|
||||
data: { type: permission },
|
||||
});
|
||||
} else {
|
||||
// Create a new permission
|
||||
data = await tx.workspacePageUserPermission.create({
|
||||
data: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
userId,
|
||||
type: permission,
|
||||
// page permission does not require invitee to accept, the accepted field will be deprecated later.
|
||||
accepted: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// If the new permission is owner, we need to revoke old owner
|
||||
if (permission === Permission.Owner) {
|
||||
await tx.workspacePageUserPermission.updateMany({
|
||||
where: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
type: Permission.Owner,
|
||||
userId: { not: userId },
|
||||
},
|
||||
data: { type: Permission.Admin },
|
||||
});
|
||||
this.logger.log(
|
||||
`Change owner of workspace ${workspaceId} page ${pageId} to user ${userId}`
|
||||
);
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
// nothing to do
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a given user is a member of a workspace and has the given or higher permission.
|
||||
* Default to read permission.
|
||||
*/
|
||||
async isMember(
|
||||
workspaceId: string,
|
||||
pageId: string,
|
||||
userId: string,
|
||||
permission: Permission = Permission.Read
|
||||
) {
|
||||
const count = await this.db.workspacePageUserPermission.count({
|
||||
where: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
userId,
|
||||
type: {
|
||||
gte: permission,
|
||||
},
|
||||
},
|
||||
});
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a page member
|
||||
* Except the owner, the owner can't be deleted.
|
||||
*/
|
||||
async deleteMember(workspaceId: string, pageId: string, userId: string) {
|
||||
const { count } = await this.db.workspacePageUserPermission.deleteMany({
|
||||
where: {
|
||||
workspaceId,
|
||||
pageId,
|
||||
userId,
|
||||
type: {
|
||||
// We shouldn't revoke owner permission, should auto deleted by workspace/user delete cascading
|
||||
not: Permission.Owner,
|
||||
},
|
||||
},
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
Reference in New Issue
Block a user