From 50847be871f054ee1874021374ccd9cd2685484d Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:37:45 +0000 Subject: [PATCH] WIP --- .../repos/page/page-permission.repo.ts | 83 ++++++++++++++----- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/apps/server/src/database/repos/page/page-permission.repo.ts b/apps/server/src/database/repos/page/page-permission.repo.ts index 4ec7e6db..ebb17e51 100644 --- a/apps/server/src/database/repos/page/page-permission.repo.ts +++ b/apps/server/src/database/repos/page/page-permission.repo.ts @@ -10,7 +10,7 @@ import { } from '@docmost/db/types/entity.types'; import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; import { executeWithPagination } from '@docmost/db/pagination/pagination'; -import { sql } from 'kysely'; +import { sql, SqlBool } from 'kysely'; import { GroupRepo } from '@docmost/db/repos/group/group.repo'; import { GroupUserRepo } from '@docmost/db/repos/group/group-user.repo'; @@ -46,7 +46,10 @@ export class PagePermissionRepo { .executeTakeFirst(); } - async deletePageAccess(pageId: string, trx?: KyselyTransaction): Promise { + async deletePageAccess( + pageId: string, + trx?: KyselyTransaction, + ): Promise { const db = dbOrTx(this.db, trx); await db.deleteFrom('pageAccess').where('pageId', '=', pageId).execute(); } @@ -57,10 +60,7 @@ export class PagePermissionRepo { ): Promise { if (permissions.length === 0) return; const db = dbOrTx(this.db, trx); - await db - .insertInto('pagePermissions') - .values(permissions) - .execute(); + await db.insertInto('pagePermissions').values(permissions).execute(); } async findPagePermissionByUserId( @@ -236,15 +236,27 @@ export class PagePermissionRepo { ): Promise<{ role: string } | undefined> { const result = await this.db .selectFrom('pageAccess') - .innerJoin('pagePermissions', 'pagePermissions.pageAccessId', 'pageAccess.id') + .innerJoin( + 'pagePermissions', + 'pagePermissions.pageAccessId', + 'pageAccess.id', + ) .select(['pagePermissions.role']) .where('pageAccess.pageId', '=', pageId) .where('pagePermissions.userId', '=', userId) .unionAll( this.db .selectFrom('pageAccess') - .innerJoin('pagePermissions', 'pagePermissions.pageAccessId', 'pageAccess.id') - .innerJoin('groupUsers', 'groupUsers.groupId', 'pagePermissions.groupId') + .innerJoin( + 'pagePermissions', + 'pagePermissions.pageAccessId', + 'pageAccess.id', + ) + .innerJoin( + 'groupUsers', + 'groupUsers.groupId', + 'pagePermissions.groupId', + ) .select(['pagePermissions.role']) .where('pageAccess.pageId', '=', pageId) .where('groupUsers.userId', '=', userId), @@ -256,7 +268,9 @@ export class PagePermissionRepo { async findRestrictedAncestor( pageId: string, - ): Promise<{ pageId: string; accessLevel: string; depth: number } | undefined> { + ): Promise< + { pageId: string; accessLevel: string; depth: number } | undefined + > { return this.db .selectFrom('pageHierarchy') .innerJoin('pageAccess', 'pageAccess.pageId', 'pageHierarchy.ancestorId') @@ -345,7 +359,11 @@ export class PagePermissionRepo { async getUserPageAccessLevel( userId: string, pageId: string, - ): Promise<{ hasRestriction: boolean; canAccess: boolean; canEdit: boolean }> { + ): Promise<{ + hasRestriction: boolean; + canAccess: boolean; + canEdit: boolean; + }> { const result = await this.db .selectFrom('pages') .select((eb) => [ @@ -384,7 +402,11 @@ export class PagePermissionRepo { ) .leftJoin('pagePermissions', (join) => join - .onRef('pagePermissions.pageAccessId', '=', 'pageAccess.id') + .onRef( + 'pagePermissions.pageAccessId', + '=', + 'pageAccess.id', + ) .on((eb2) => eb2.or([ eb2('pagePermissions.userId', '=', userId), @@ -424,7 +446,11 @@ export class PagePermissionRepo { ) .leftJoin('pagePermissions', (join) => join - .onRef('pagePermissions.pageAccessId', '=', 'pageAccess.id') + .onRef( + 'pagePermissions.pageAccessId', + '=', + 'pageAccess.id', + ) .on('pagePermissions.role', '=', 'writer') .on((eb2) => eb2.or([ @@ -491,7 +517,11 @@ export class PagePermissionRepo { ) .leftJoin('pagePermissions', (join) => join - .onRef('pagePermissions.pageAccessId', '=', 'pageAccess.id') + .onRef( + 'pagePermissions.pageAccessId', + '=', + 'pageAccess.id', + ) .on('pagePermissions.role', '=', 'writer') .on((eb2) => eb2.or([ @@ -518,7 +548,7 @@ export class PagePermissionRepo { .end() .as('canEdit'), ) - .where('pages.id', 'in', pageIds) + .where(sql`pages.id = ANY(${pageIds}::uuid[])`) // Filter: user must have access (any permission on all restricted ancestors) .where(({ not, exists, selectFrom }) => not( @@ -578,13 +608,20 @@ export class PagePermissionRepo { */ async hasRestrictedPagesInSpace(spaceId: string): Promise { const result = await this.db - .selectFrom('pageAccess') - .innerJoin('pages', 'pages.id', 'pageAccess.pageId') - .select('pageAccess.id') - .where('pages.spaceId', '=', spaceId) + .selectNoFrom((eb) => + eb + .exists( + eb + .selectFrom('pageAccess') + .innerJoin('pages', 'pages.id', 'pageAccess.pageId') + .select(sql`1`.as('one')) + .where('pages.spaceId', '=', spaceId), + ) + .as('exists'), + ) .executeTakeFirst(); - return !!result; + return Boolean(result?.exists); } /** @@ -658,7 +695,11 @@ export class PagePermissionRepo { .distinct() .as('restricted'), (join) => - join.onRef('restricted.restrictedDescendant', '=', 'subtree.descendantId'), + join.onRef( + 'restricted.restrictedDescendant', + '=', + 'subtree.descendantId', + ), ) .select('subtree.descendantId') .distinct()