diff --git a/packages/backend/server/src/base/job/queue/__tests__/queue.spec.ts b/packages/backend/server/src/base/job/queue/__tests__/queue.spec.ts index 6eea4efdb9..a0fe401c2c 100644 --- a/packages/backend/server/src/base/job/queue/__tests__/queue.spec.ts +++ b/packages/backend/server/src/base/job/queue/__tests__/queue.spec.ts @@ -60,6 +60,9 @@ test.before(async () => { // which will keep the test process alive to timeout. stalledInterval: 100, }, + queue: { + defaultJobOptions: { delay: 1000 }, + }, }, }), JobModule.forRoot(), diff --git a/packages/backend/server/src/core/permission/service.ts b/packages/backend/server/src/core/permission/service.ts index 6e04794217..7a0a4e9cd5 100644 --- a/packages/backend/server/src/core/permission/service.ts +++ b/packages/backend/server/src/core/permission/service.ts @@ -613,6 +613,8 @@ export class PermissionService { }), ]); + const defaultPageRole = pageEntity?.defaultRole ?? DocRole.Manager; + if ( // Page role exists, check it first (roleEntity && roleEntity.type >= role) || @@ -625,7 +627,7 @@ export class PermissionService { workspaceRoleEntity.type !== WorkspaceRole.External && Math.max( roleEntity?.type ?? Number.MIN_SAFE_INTEGER, - pageEntity?.defaultRole ?? Number.MIN_SAFE_INTEGER + defaultPageRole ) >= role) ) { return true; @@ -638,9 +640,7 @@ export class PermissionService { ? WorkspaceRole[workspaceRoleEntity.type] : undefined, pageRole: roleEntity ? DocRole[roleEntity.type] : undefined, - pageDefaultRole: pageEntity - ? DocRole[pageEntity.defaultRole] - : undefined, + pageDefaultRole: DocRole[defaultPageRole], requiredRole: DocRole[role], action, }; diff --git a/packages/backend/server/src/core/workspaces/resolvers/doc.ts b/packages/backend/server/src/core/workspaces/resolvers/doc.ts index 95babf4096..93ecc1c754 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/doc.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/doc.ts @@ -155,7 +155,8 @@ export class WorkspaceDocResolver { constructor( private readonly prisma: PrismaClient, - private readonly permission: PermissionService + private readonly permission: PermissionService, + private readonly models: Models ) {} @ResolveField(() => [DocType], { @@ -209,17 +210,19 @@ export class WorkspaceDocResolver { }, }); - if (!doc) { - return { - docId, - workspaceId: workspace.id, - mode: PublicDocMode.Page, - public: false, - defaultRole: DocRole.Manager, - }; + if (doc) { + return doc; } - return doc; + await this.tryFixDocOwner(workspace.id, docId); + + return { + docId, + workspaceId: workspace.id, + mode: PublicDocMode.Page, + public: false, + defaultRole: DocRole.Manager, + }; } @Mutation(() => DocType, { @@ -331,6 +334,58 @@ export class WorkspaceDocResolver { return this.permission.revokePublicPage(docId.workspace, docId.guid); } + + private async tryFixDocOwner(workspaceId: string, docId: string) { + const exists = await this.models.doc.exists(workspaceId, docId); + + // skip if doc not even exists + if (!exists) { + return; + } + + const owner = await this.prisma.workspaceDocUserPermission.findFirst({ + where: { + workspaceId, + docId, + type: DocRole.Owner, + }, + }); + + // skip if owner of already exists + if (owner) { + return; + } + + // try snapshot.createdBy first + const snapshot = await this.prisma.snapshot.findUnique({ + select: { + createdBy: true, + }, + where: { + workspaceId_id: { + workspaceId, + id: docId, + }, + }, + }); + + let fixedOwner = snapshot?.createdBy; + + // try workspace.owner + if (!fixedOwner) { + const owner = await this.permission.getWorkspaceOwner(workspaceId); + fixedOwner = owner.id; + } + + await this.prisma.workspaceDocUserPermission.create({ + data: { + workspaceId, + docId, + userId: fixedOwner, + type: DocRole.Owner, + }, + }); + } } @Resolver(() => DocType)