refactor(server): remove never used column in page permission (#9985)
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The primary key for the `workspace_page_user_permissions` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
- You are about to drop the column `accepted` on the `workspace_page_user_permissions` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `id` on the `workspace_page_user_permissions` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "workspace_page_user_permissions_workspace_id_page_id_user_i_key";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "workspace_page_user_permissions" DROP CONSTRAINT "workspace_page_user_permissions_pkey",
|
||||||
|
DROP COLUMN "accepted",
|
||||||
|
DROP COLUMN "id",
|
||||||
|
ADD CONSTRAINT "workspace_page_user_permissions_pkey" PRIMARY KEY ("workspace_id", "page_id", "user_id");
|
||||||
@@ -161,20 +161,17 @@ model WorkspaceUserPermission {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model WorkspacePageUserPermission {
|
model WorkspacePageUserPermission {
|
||||||
id String @id @default(uuid()) @db.VarChar
|
|
||||||
workspaceId String @map("workspace_id") @db.VarChar
|
workspaceId String @map("workspace_id") @db.VarChar
|
||||||
pageId String @map("page_id") @db.VarChar
|
pageId String @map("page_id") @db.VarChar
|
||||||
userId String @map("user_id") @db.VarChar
|
userId String @map("user_id") @db.VarChar
|
||||||
// External/Reader/Editor/Manager/Owner
|
// External/Reader/Editor/Manager/Owner
|
||||||
type Int @db.SmallInt
|
type Int @db.SmallInt
|
||||||
/// Whether the permission invitation is accepted by the user
|
|
||||||
accepted Boolean @default(false)
|
|
||||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(3)
|
||||||
|
|
||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@unique([workspaceId, pageId, userId])
|
@@id([workspaceId, pageId, userId])
|
||||||
@@map("workspace_page_user_permissions")
|
@@map("workspace_page_user_permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,3 +84,6 @@ export type GraphqlContext = {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class GqlModule {}
|
export class GqlModule {}
|
||||||
|
|
||||||
|
export * from './pagination';
|
||||||
|
export { registerObjectType } from './register';
|
||||||
|
|||||||
127
packages/backend/server/src/base/graphql/pagination.ts
Normal file
127
packages/backend/server/src/base/graphql/pagination.ts
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import { Type } from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
Field,
|
||||||
|
FieldMiddleware,
|
||||||
|
InputType,
|
||||||
|
Int,
|
||||||
|
MiddlewareContext,
|
||||||
|
NextFn,
|
||||||
|
ObjectType,
|
||||||
|
} from '@nestjs/graphql';
|
||||||
|
|
||||||
|
const parseCursorMiddleware: FieldMiddleware = async (
|
||||||
|
_ctx: MiddlewareContext,
|
||||||
|
next: NextFn
|
||||||
|
) => {
|
||||||
|
const value = await next();
|
||||||
|
return value === undefined || value === null ? null : decode(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
@InputType()
|
||||||
|
export class PaginationInput {
|
||||||
|
@Field(() => Int, {
|
||||||
|
nullable: true,
|
||||||
|
description: 'returns the first n elements from the list.',
|
||||||
|
defaultValue: 10,
|
||||||
|
})
|
||||||
|
first!: number;
|
||||||
|
|
||||||
|
@Field(() => Int, {
|
||||||
|
nullable: true,
|
||||||
|
description: 'ignore the first n elements from the list.',
|
||||||
|
defaultValue: 0,
|
||||||
|
})
|
||||||
|
offset!: number;
|
||||||
|
|
||||||
|
@Field(() => String, {
|
||||||
|
nullable: true,
|
||||||
|
description:
|
||||||
|
'returns the elements in the list that come after the specified cursor.',
|
||||||
|
middleware: [parseCursorMiddleware],
|
||||||
|
})
|
||||||
|
after!: string | null;
|
||||||
|
|
||||||
|
@Field(() => String, {
|
||||||
|
nullable: true,
|
||||||
|
description:
|
||||||
|
'returns the elements in the list that come before the specified cursor.',
|
||||||
|
middleware: [parseCursorMiddleware],
|
||||||
|
})
|
||||||
|
before!: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const encode = (input: string) => Buffer.from(input).toString('base64');
|
||||||
|
const decode = (base64String: string) =>
|
||||||
|
Buffer.from(base64String, 'base64').toString('utf-8');
|
||||||
|
|
||||||
|
export function paginate<T>(
|
||||||
|
list: T[],
|
||||||
|
cursorField: keyof T,
|
||||||
|
paginationInput: PaginationInput,
|
||||||
|
total: number
|
||||||
|
): PaginatedType<T> {
|
||||||
|
const edges = list.map(item => ({
|
||||||
|
node: item,
|
||||||
|
cursor: encode(String(item[cursorField])),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalCount: total,
|
||||||
|
edges,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: edges.length >= paginationInput.first,
|
||||||
|
hasPreviousPage: paginationInput.offset > 0,
|
||||||
|
endCursor: edges.length ? edges[edges.length - 1].cursor : null,
|
||||||
|
startCursor: edges.length ? edges[0].cursor : null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PaginatedType<T> {
|
||||||
|
totalCount: number;
|
||||||
|
edges: {
|
||||||
|
cursor: string;
|
||||||
|
node: T;
|
||||||
|
}[];
|
||||||
|
pageInfo: PageInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class PageInfo {
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
startCursor?: string | null;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
endCursor?: string | null;
|
||||||
|
|
||||||
|
@Field()
|
||||||
|
hasNextPage!: boolean;
|
||||||
|
|
||||||
|
@Field()
|
||||||
|
hasPreviousPage!: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Paginated<T>(classRef: Type<T>): any {
|
||||||
|
@ObjectType(`${classRef.name}Edge`)
|
||||||
|
abstract class EdgeType {
|
||||||
|
@Field(() => String)
|
||||||
|
cursor!: string;
|
||||||
|
|
||||||
|
@Field(() => classRef)
|
||||||
|
node!: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ObjectType({ isAbstract: true })
|
||||||
|
abstract class PaginatedType {
|
||||||
|
@Field(() => Int)
|
||||||
|
totalCount!: number;
|
||||||
|
|
||||||
|
@Field(() => [EdgeType])
|
||||||
|
edges!: EdgeType[];
|
||||||
|
|
||||||
|
@Field(() => PageInfo)
|
||||||
|
pageInfo!: PageInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PaginatedType;
|
||||||
|
}
|
||||||
@@ -15,8 +15,13 @@ export {
|
|||||||
} from './config';
|
} from './config';
|
||||||
export * from './error';
|
export * from './error';
|
||||||
export { EventBus, OnEvent } from './event';
|
export { EventBus, OnEvent } from './event';
|
||||||
export type { GraphqlContext } from './graphql';
|
export {
|
||||||
export { registerObjectType } from './graphql/register';
|
type GraphqlContext,
|
||||||
|
paginate,
|
||||||
|
Paginated,
|
||||||
|
PaginationInput,
|
||||||
|
registerObjectType,
|
||||||
|
} from './graphql';
|
||||||
export * from './guard';
|
export * from './guard';
|
||||||
export { CryptoHelper, URLHelper } from './helpers';
|
export { CryptoHelper, URLHelper } from './helpers';
|
||||||
export { AFFiNELogger } from './logger';
|
export { AFFiNELogger } from './logger';
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ export class PermissionService {
|
|||||||
const { workspaceId, docId, editor } = payload;
|
const { workspaceId, docId, editor } = payload;
|
||||||
|
|
||||||
await this.prisma.$queryRaw`
|
await this.prisma.$queryRaw`
|
||||||
INSERT INTO "workspace_page_user_permissions" ("workspace_id", "page_id", "user_id", "type", "accepted", "created_at", "updated_at")
|
INSERT INTO "workspace_page_user_permissions" ("workspace_id", "page_id", "user_id", "type", "created_at")
|
||||||
VALUES (${workspaceId}, ${docId}, ${editor}, ${DocRole.Owner}, true, now(), now())
|
VALUES (${workspaceId}, ${docId}, ${editor}, ${DocRole.Owner}, now())
|
||||||
ON CONFLICT ("workspace_id", "page_id", "user_id")
|
ON CONFLICT ("workspace_id", "page_id", "user_id")
|
||||||
DO NOTHING
|
DO NOTHING
|
||||||
`;
|
`;
|
||||||
@@ -576,7 +576,6 @@ export class PermissionService {
|
|||||||
workspaceId: ws,
|
workspaceId: ws,
|
||||||
pageId: page,
|
pageId: page,
|
||||||
userId: user,
|
userId: user,
|
||||||
accepted: true,
|
|
||||||
type: {
|
type: {
|
||||||
gte: role,
|
gte: role,
|
||||||
},
|
},
|
||||||
@@ -658,65 +657,48 @@ export class PermissionService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async grantPage(
|
async grantPage(ws: string, page: string, user: string, permission: DocRole) {
|
||||||
ws: string,
|
const [p] = await this.prisma.$transaction(
|
||||||
page: string,
|
[
|
||||||
user: string,
|
this.prisma.workspacePageUserPermission.upsert({
|
||||||
permission: DocRole
|
where: {
|
||||||
): Promise<string> {
|
workspaceId_pageId_userId: {
|
||||||
const data = await this.prisma.workspacePageUserPermission.findFirst({
|
workspaceId: ws,
|
||||||
where: {
|
pageId: page,
|
||||||
workspaceId: ws,
|
userId: user,
|
||||||
pageId: page,
|
|
||||||
userId: user,
|
|
||||||
accepted: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
const [p] = await this.prisma.$transaction(
|
|
||||||
[
|
|
||||||
this.prisma.workspacePageUserPermission.update({
|
|
||||||
where: {
|
|
||||||
id: data.id,
|
|
||||||
},
|
},
|
||||||
data: {
|
},
|
||||||
type: permission,
|
update: {
|
||||||
},
|
type: permission,
|
||||||
}),
|
},
|
||||||
|
create: {
|
||||||
|
workspaceId: ws,
|
||||||
|
pageId: page,
|
||||||
|
userId: user,
|
||||||
|
type: permission,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
// If the new permission is owner, we need to revoke old owner
|
// If the new permission is owner, we need to revoke old owner
|
||||||
permission === DocRole.Owner
|
permission === DocRole.Owner
|
||||||
? this.prisma.workspacePageUserPermission.updateMany({
|
? this.prisma.workspacePageUserPermission.updateMany({
|
||||||
where: {
|
where: {
|
||||||
workspaceId: ws,
|
workspaceId: ws,
|
||||||
pageId: page,
|
pageId: page,
|
||||||
type: DocRole.Owner,
|
type: DocRole.Owner,
|
||||||
userId: {
|
userId: {
|
||||||
not: user,
|
not: user,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data: {
|
},
|
||||||
type: DocRole.Manager,
|
data: {
|
||||||
},
|
type: DocRole.Manager,
|
||||||
})
|
},
|
||||||
: null,
|
})
|
||||||
].filter(Boolean) as Prisma.PrismaPromise<any>[]
|
: null,
|
||||||
);
|
].filter(Boolean) as Prisma.PrismaPromise<any>[]
|
||||||
|
);
|
||||||
|
|
||||||
return p.id;
|
return p;
|
||||||
}
|
|
||||||
|
|
||||||
return this.prisma.workspacePageUserPermission
|
|
||||||
.create({
|
|
||||||
data: {
|
|
||||||
workspaceId: ws,
|
|
||||||
pageId: page,
|
|
||||||
userId: user,
|
|
||||||
type: permission,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(p => p.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async revokePage(ws: string, page: string, users: string[]) {
|
async revokePage(ws: string, page: string, users: string[]) {
|
||||||
@@ -746,14 +728,11 @@ export class PermissionService {
|
|||||||
if (userIds.length === 0) {
|
if (userIds.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if (role === DocRole.Owner) {
|
if (role === DocRole.Owner && userIds.length > 1) {
|
||||||
if (userIds.length > 1) {
|
throw new SpaceShouldHaveOnlyOneOwner({ spaceId: workspaceId });
|
||||||
throw new SpaceShouldHaveOnlyOneOwner({ spaceId: workspaceId });
|
|
||||||
}
|
|
||||||
return [await this.grantPage(workspaceId, pageId, userIds[0], role)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = await this.prisma.$transaction(async tx =>
|
return await this.prisma.$transaction(async tx =>
|
||||||
Promise.all(
|
Promise.all(
|
||||||
userIds.map(id =>
|
userIds.map(id =>
|
||||||
tx.workspacePageUserPermission.upsert({
|
tx.workspacePageUserPermission.upsert({
|
||||||
@@ -777,7 +756,6 @@ export class PermissionService {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return ret.map(p => p.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updatePagePermission(
|
async updatePagePermission(
|
||||||
@@ -798,14 +776,17 @@ export class PermissionService {
|
|||||||
return this.grantPage(workspaceId, pageId, userId, role);
|
return this.grantPage(workspaceId, pageId, userId, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id } = await this.prisma.workspacePageUserPermission.update({
|
return await this.prisma.workspacePageUserPermission.update({
|
||||||
where: {
|
where: {
|
||||||
id: permission.id,
|
workspaceId_pageId_userId: {
|
||||||
|
workspaceId,
|
||||||
|
pageId,
|
||||||
|
userId,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
type: role,
|
type: role,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
Args,
|
Args,
|
||||||
Field,
|
Field,
|
||||||
InputType,
|
InputType,
|
||||||
Int,
|
|
||||||
Mutation,
|
Mutation,
|
||||||
ObjectType,
|
ObjectType,
|
||||||
Parent,
|
Parent,
|
||||||
@@ -21,6 +20,9 @@ import {
|
|||||||
ExpectToRevokePublicPage,
|
ExpectToRevokePublicPage,
|
||||||
ExpectToUpdateDocUserRole,
|
ExpectToUpdateDocUserRole,
|
||||||
PageIsNotPublic,
|
PageIsNotPublic,
|
||||||
|
paginate,
|
||||||
|
Paginated,
|
||||||
|
PaginationInput,
|
||||||
registerObjectType,
|
registerObjectType,
|
||||||
} from '../../../base';
|
} from '../../../base';
|
||||||
import { CurrentUser } from '../../auth';
|
import { CurrentUser } from '../../auth';
|
||||||
@@ -34,7 +36,6 @@ import {
|
|||||||
PublicPageMode,
|
PublicPageMode,
|
||||||
WorkspaceRole,
|
WorkspaceRole,
|
||||||
} from '../../permission';
|
} from '../../permission';
|
||||||
import { UserType } from '../../user';
|
|
||||||
import { DocID } from '../../utils/doc';
|
import { DocID } from '../../utils/doc';
|
||||||
import { WorkspaceType } from '../types';
|
import { WorkspaceType } from '../types';
|
||||||
|
|
||||||
@@ -73,65 +74,23 @@ class GrantDocUserRolesInput {
|
|||||||
userIds!: string[];
|
userIds!: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@InputType()
|
|
||||||
class PageGrantedUsersInput {
|
|
||||||
@Field(() => Int)
|
|
||||||
first!: number;
|
|
||||||
|
|
||||||
@Field(() => Int)
|
|
||||||
offset?: number;
|
|
||||||
|
|
||||||
@Field(() => String, { description: 'Cursor', nullable: true })
|
|
||||||
after?: string;
|
|
||||||
|
|
||||||
@Field(() => String, { description: 'Cursor', nullable: true })
|
|
||||||
before?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
class GrantedDocUserType {
|
class GrantedDocUserType {
|
||||||
@Field(() => UserType)
|
@Field(() => String)
|
||||||
user!: UserType;
|
workspaceId!: string;
|
||||||
|
|
||||||
@Field(() => DocRole)
|
|
||||||
role!: DocRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ObjectType()
|
|
||||||
class PageInfo {
|
|
||||||
@Field(() => String, { nullable: true })
|
|
||||||
startCursor?: string;
|
|
||||||
|
|
||||||
@Field(() => String, { nullable: true })
|
|
||||||
endCursor?: string;
|
|
||||||
|
|
||||||
@Field(() => Boolean)
|
|
||||||
hasNextPage!: boolean;
|
|
||||||
|
|
||||||
@Field(() => Boolean)
|
|
||||||
hasPreviousPage!: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ObjectType()
|
|
||||||
class GrantedDocUserEdge {
|
|
||||||
@Field(() => GrantedDocUserType)
|
|
||||||
user!: GrantedDocUserType;
|
|
||||||
|
|
||||||
@Field(() => String)
|
@Field(() => String)
|
||||||
cursor!: string;
|
pageId!: string;
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
userId!: string;
|
||||||
|
|
||||||
|
@Field(() => DocRole, { name: 'role' })
|
||||||
|
type!: DocRole;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
class GrantedDocUsersConnection {
|
class PaginatedGrantedDocUserType extends Paginated(GrantedDocUserType) {}
|
||||||
@Field(() => Int)
|
|
||||||
totalCount!: number;
|
|
||||||
|
|
||||||
@Field(() => [GrantedDocUserEdge])
|
|
||||||
edges!: GrantedDocUserEdge[];
|
|
||||||
|
|
||||||
@Field(() => PageInfo)
|
|
||||||
pageInfo!: PageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DocPermissions = registerObjectType<DocActionPermissions>(
|
const DocPermissions = registerObjectType<DocActionPermissions>(
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
@@ -261,16 +220,15 @@ export class PagePermissionResolver {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => GrantedDocUsersConnection, {
|
@ResolveField(() => PaginatedGrantedDocUserType, {
|
||||||
description: 'Page granted users list',
|
description: 'Page granted users list',
|
||||||
complexity: 4,
|
complexity: 4,
|
||||||
})
|
})
|
||||||
async pageGrantedUsersList(
|
async pageGrantedUsersList(
|
||||||
@Parent() workspace: WorkspaceType,
|
@Parent() workspace: WorkspaceType,
|
||||||
@Args('pageId') pageId: string,
|
@Args('pageId') pageId: string,
|
||||||
@Args('pageGrantedUsersInput')
|
@Args('pagination') pagination: PaginationInput
|
||||||
pageGrantedUsersInput: PageGrantedUsersInput
|
): Promise<PaginatedGrantedDocUserType> {
|
||||||
): Promise<GrantedDocUsersConnection> {
|
|
||||||
const docId = new DocID(pageId, workspace.id);
|
const docId = new DocID(pageId, workspace.id);
|
||||||
const [permissions, totalCount] = await this.prisma.$transaction(tx => {
|
const [permissions, totalCount] = await this.prisma.$transaction(tx => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
@@ -279,19 +237,11 @@ export class PagePermissionResolver {
|
|||||||
workspaceId: workspace.id,
|
workspaceId: workspace.id,
|
||||||
pageId: docId.guid,
|
pageId: docId.guid,
|
||||||
},
|
},
|
||||||
include: {
|
|
||||||
user: true,
|
|
||||||
},
|
|
||||||
orderBy: {
|
orderBy: {
|
||||||
createdAt: 'desc',
|
createdAt: 'desc',
|
||||||
},
|
},
|
||||||
take: pageGrantedUsersInput.first,
|
take: pagination.first,
|
||||||
skip: pageGrantedUsersInput.offset,
|
skip: pagination.offset,
|
||||||
cursor: pageGrantedUsersInput.after
|
|
||||||
? {
|
|
||||||
id: pageGrantedUsersInput.after,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
}),
|
}),
|
||||||
tx.workspacePageUserPermission.count({
|
tx.workspacePageUserPermission.count({
|
||||||
where: {
|
where: {
|
||||||
@@ -302,31 +252,7 @@ export class PagePermissionResolver {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return paginate(permissions, 'createdAt', pagination, totalCount);
|
||||||
totalCount,
|
|
||||||
edges: permissions.map(permission => ({
|
|
||||||
user: {
|
|
||||||
user: {
|
|
||||||
id: permission.user.id,
|
|
||||||
name: permission.user.name,
|
|
||||||
email: permission.user.email,
|
|
||||||
avatarUrl: permission.user.avatarUrl,
|
|
||||||
emailVerified: permission.user.emailVerifiedAt !== null,
|
|
||||||
hasPassword: permission.user.password !== null,
|
|
||||||
},
|
|
||||||
role: permission.type,
|
|
||||||
},
|
|
||||||
cursor: permission.id,
|
|
||||||
})),
|
|
||||||
pageInfo: {
|
|
||||||
startCursor: permissions.at(0)?.id,
|
|
||||||
endCursor: permissions.at(-1)?.id,
|
|
||||||
hasNextPage: totalCount > pageGrantedUsersInput.first,
|
|
||||||
hasPreviousPage:
|
|
||||||
pageGrantedUsersInput.offset !== undefined &&
|
|
||||||
pageGrantedUsersInput.offset > 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -127,8 +127,6 @@ export class PageModel extends BaseModel {
|
|||||||
pageId,
|
pageId,
|
||||||
userId,
|
userId,
|
||||||
type: permission,
|
type: permission,
|
||||||
// page permission does not require invitee to accept, the accepted field will be deprecated later.
|
|
||||||
accepted: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -383,20 +383,16 @@ input GrantDocUserRolesInput {
|
|||||||
workspaceId: String!
|
workspaceId: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type GrantedDocUserEdge {
|
|
||||||
cursor: String!
|
|
||||||
user: GrantedDocUserType!
|
|
||||||
}
|
|
||||||
|
|
||||||
type GrantedDocUserType {
|
type GrantedDocUserType {
|
||||||
|
pageId: String!
|
||||||
role: DocRole!
|
role: DocRole!
|
||||||
user: UserType!
|
userId: String!
|
||||||
|
workspaceId: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type GrantedDocUsersConnection {
|
type GrantedDocUserTypeEdge {
|
||||||
edges: [GrantedDocUserEdge!]!
|
cursor: String!
|
||||||
pageInfo: PageInfo!
|
node: GrantedDocUserType!
|
||||||
totalCount: Int!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type InvalidEmailDataType {
|
type InvalidEmailDataType {
|
||||||
@@ -685,16 +681,6 @@ enum OAuthProviderType {
|
|||||||
OIDC
|
OIDC
|
||||||
}
|
}
|
||||||
|
|
||||||
input PageGrantedUsersInput {
|
|
||||||
"""Cursor"""
|
|
||||||
after: String
|
|
||||||
|
|
||||||
"""Cursor"""
|
|
||||||
before: String
|
|
||||||
first: Int!
|
|
||||||
offset: Int!
|
|
||||||
}
|
|
||||||
|
|
||||||
type PageInfo {
|
type PageInfo {
|
||||||
endCursor: String
|
endCursor: String
|
||||||
hasNextPage: Boolean!
|
hasNextPage: Boolean!
|
||||||
@@ -702,6 +688,28 @@ type PageInfo {
|
|||||||
startCursor: String
|
startCursor: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PaginatedGrantedDocUserType {
|
||||||
|
edges: [GrantedDocUserTypeEdge!]!
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
totalCount: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
input PaginationInput {
|
||||||
|
"""returns the elements in the list that come after the specified cursor."""
|
||||||
|
after: String
|
||||||
|
|
||||||
|
"""
|
||||||
|
returns the elements in the list that come before the specified cursor.
|
||||||
|
"""
|
||||||
|
before: String
|
||||||
|
|
||||||
|
"""returns the first n elements from the list."""
|
||||||
|
first: Int = 10
|
||||||
|
|
||||||
|
"""ignore the first n elements from the list."""
|
||||||
|
offset: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
type PasswordLimitsType {
|
type PasswordLimitsType {
|
||||||
maxLength: Int!
|
maxLength: Int!
|
||||||
minLength: Int!
|
minLength: Int!
|
||||||
@@ -1200,7 +1208,7 @@ type WorkspaceType {
|
|||||||
owner: UserType!
|
owner: UserType!
|
||||||
|
|
||||||
"""Page granted users list"""
|
"""Page granted users list"""
|
||||||
pageGrantedUsersList(pageGrantedUsersInput: PageGrantedUsersInput!, pageId: String!): GrantedDocUsersConnection!
|
pageGrantedUsersList(pageId: String!, pagination: PaginationInput!): PaginatedGrantedDocUserType!
|
||||||
|
|
||||||
"""Cloud page metadata of workspace"""
|
"""Cloud page metadata of workspace"""
|
||||||
pageMeta(pageId: String!): WorkspacePageMeta!
|
pageMeta(pageId: String!): WorkspacePageMeta!
|
||||||
|
|||||||
Reference in New Issue
Block a user