mirror of
https://github.com/docmost/docmost.git
synced 2026-05-20 00:14:10 +08:00
POC
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
export function LogTiming() {
|
||||||
|
return function (
|
||||||
|
target: any,
|
||||||
|
propertyKey: string,
|
||||||
|
descriptor: PropertyDescriptor,
|
||||||
|
) {
|
||||||
|
const original = descriptor.value;
|
||||||
|
descriptor.value = async function (...args: any[]) {
|
||||||
|
const start = performance.now();
|
||||||
|
try {
|
||||||
|
return await original.apply(this, args);
|
||||||
|
} finally {
|
||||||
|
const ms = performance.now() - start;
|
||||||
|
console.log(
|
||||||
|
`[perm-timing] ${target.constructor.name}.${propertyKey} ${ms.toFixed(2)}ms`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return descriptor;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -13,10 +13,12 @@ import {
|
|||||||
SpaceCaslSubject,
|
SpaceCaslSubject,
|
||||||
} from '../interfaces/space-ability.type';
|
} from '../interfaces/space-ability.type';
|
||||||
import { findHighestUserSpaceRole } from '@docmost/db/repos/space/utils';
|
import { findHighestUserSpaceRole } from '@docmost/db/repos/space/utils';
|
||||||
|
import { LogTiming } from '../../../common/helpers/log-timing';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export default class SpaceAbilityFactory {
|
export default class SpaceAbilityFactory {
|
||||||
constructor(private readonly spaceMemberRepo: SpaceMemberRepo) {}
|
constructor(private readonly spaceMemberRepo: SpaceMemberRepo) {}
|
||||||
|
@LogTiming()
|
||||||
async createForUser(user: User, spaceId: string) {
|
async createForUser(user: User, spaceId: string) {
|
||||||
const userSpaceRoles = await this.spaceMemberRepo.getUserSpaceRoles(
|
const userSpaceRoles = await this.spaceMemberRepo.getUserSpaceRoles(
|
||||||
user.id,
|
user.id,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
executeWithCursorPagination,
|
executeWithCursorPagination,
|
||||||
} from '@docmost/db/pagination/cursor-pagination';
|
} from '@docmost/db/pagination/cursor-pagination';
|
||||||
import { PagePermissionMember } from './types/page-permission.types';
|
import { PagePermissionMember } from './types/page-permission.types';
|
||||||
|
import { LogTiming } from '../../../common/helpers/log-timing';
|
||||||
|
|
||||||
export { PagePermissionMember } from './types/page-permission.types';
|
export { PagePermissionMember } from './types/page-permission.types';
|
||||||
|
|
||||||
@@ -360,6 +361,7 @@ export class PagePermissionRepo {
|
|||||||
/**
|
/**
|
||||||
* Check if user can access a page by verifying they have permission on ALL restricted ancestors.
|
* Check if user can access a page by verifying they have permission on ALL restricted ancestors.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async canUserAccessPage(userId: string, pageId: string): Promise<boolean> {
|
async canUserAccessPage(userId: string, pageId: string): Promise<boolean> {
|
||||||
const deniedAncestor = await this.db
|
const deniedAncestor = await this.db
|
||||||
.withRecursive('ancestors', (qb) =>
|
.withRecursive('ancestors', (qb) =>
|
||||||
@@ -404,6 +406,7 @@ export class PagePermissionRepo {
|
|||||||
* - array_agg(role ORDER BY depth)[1]: role on the nearest restricted ancestor
|
* - array_agg(role ORDER BY depth)[1]: role on the nearest restricted ancestor
|
||||||
* - Zero rows (no restricted ancestors): both NULL → defer to space permissions (true)
|
* - Zero rows (no restricted ancestors): both NULL → defer to space permissions (true)
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async canUserEditPage(
|
async canUserEditPage(
|
||||||
userId: string,
|
userId: string,
|
||||||
pageId: string,
|
pageId: string,
|
||||||
@@ -460,6 +463,7 @@ export class PagePermissionRepo {
|
|||||||
* - canAccess: user has permission on all restricted ancestors (always true if no restrictions)
|
* - canAccess: user has permission on all restricted ancestors (always true if no restrictions)
|
||||||
* - canEdit: user has writer on nearest restricted ancestor (always true if no restrictions)
|
* - canEdit: user has writer on nearest restricted ancestor (always true if no restrictions)
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async getUserPageAccessLevel(
|
async getUserPageAccessLevel(
|
||||||
userId: string,
|
userId: string,
|
||||||
pageId: string,
|
pageId: string,
|
||||||
@@ -670,6 +674,7 @@ export class PagePermissionRepo {
|
|||||||
* Returns page IDs with their permission level (canEdit).
|
* Returns page IDs with their permission level (canEdit).
|
||||||
* Single query implementation for efficiency.
|
* Single query implementation for efficiency.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async filterAccessiblePageIds(opts: {
|
async filterAccessiblePageIds(opts: {
|
||||||
pageIds: string[];
|
pageIds: string[];
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -747,6 +752,7 @@ export class PagePermissionRepo {
|
|||||||
return results.map((r) => r.id);
|
return results.map((r) => r.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LogTiming()
|
||||||
async filterAccessiblePageIdsWithPermissions(
|
async filterAccessiblePageIdsWithPermissions(
|
||||||
pageIds: string[],
|
pageIds: string[],
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -877,6 +883,7 @@ export class PagePermissionRepo {
|
|||||||
* Check if a page or any of its ancestors has restrictions.
|
* Check if a page or any of its ancestors has restrictions.
|
||||||
* Used to determine if page-level permission checks are needed.
|
* Used to determine if page-level permission checks are needed.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async hasRestrictedAncestor(pageId: string): Promise<boolean> {
|
async hasRestrictedAncestor(pageId: string): Promise<boolean> {
|
||||||
const result = await this.db
|
const result = await this.db
|
||||||
.withRecursive('ancestors', (qb) =>
|
.withRecursive('ancestors', (qb) =>
|
||||||
@@ -903,6 +910,7 @@ export class PagePermissionRepo {
|
|||||||
* Check if any page in a space has restrictions.
|
* Check if any page in a space has restrictions.
|
||||||
* Used as a quick check to skip heavy permission filtering when no restrictions exist.
|
* Used as a quick check to skip heavy permission filtering when no restrictions exist.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async hasRestrictedPagesInSpace(spaceId: string): Promise<boolean> {
|
async hasRestrictedPagesInSpace(spaceId: string): Promise<boolean> {
|
||||||
const result = await this.db
|
const result = await this.db
|
||||||
.selectNoFrom((eb) =>
|
.selectNoFrom((eb) =>
|
||||||
@@ -924,6 +932,7 @@ export class PagePermissionRepo {
|
|||||||
* Given a list of parent page IDs, return which ones have at least one accessible child.
|
* Given a list of parent page IDs, return which ones have at least one accessible child.
|
||||||
* Efficient batch query for sidebar hasChildren calculation.
|
* Efficient batch query for sidebar hasChildren calculation.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async getParentIdsWithAccessibleChildren(
|
async getParentIdsWithAccessibleChildren(
|
||||||
parentIds: string[],
|
parentIds: string[],
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -1000,6 +1009,7 @@ export class PagePermissionRepo {
|
|||||||
* Used to filter pages from public shares - if a page is restricted, it and all its
|
* Used to filter pages from public shares - if a page is restricted, it and all its
|
||||||
* children should be hidden.
|
* children should be hidden.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async getRestrictedSubtreeIds(rootPageId: string): Promise<string[]> {
|
async getRestrictedSubtreeIds(rootPageId: string): Promise<string[]> {
|
||||||
const results = await this.db
|
const results = await this.db
|
||||||
.withRecursive('descendants', (qb) =>
|
.withRecursive('descendants', (qb) =>
|
||||||
@@ -1061,6 +1071,7 @@ export class PagePermissionRepo {
|
|||||||
* access the page (have permission on ALL restricted ancestors).
|
* access the page (have permission on ALL restricted ancestors).
|
||||||
* Returns all userIds if the page has no restricted ancestors.
|
* Returns all userIds if the page has no restricted ancestors.
|
||||||
*/
|
*/
|
||||||
|
@LogTiming()
|
||||||
async getUserIdsWithPageAccess(
|
async getUserIdsWithPageAccess(
|
||||||
pageId: string,
|
pageId: string,
|
||||||
userIds: string[],
|
userIds: string[],
|
||||||
|
|||||||
Reference in New Issue
Block a user