feat(core): guard service (#9816)

This commit is contained in:
EYHN
2025-02-10 07:26:38 +08:00
committed by GitHub
parent 879157b938
commit 92f4f0c2d9
89 changed files with 1520 additions and 522 deletions

View File

@@ -11,13 +11,13 @@ export class PermissionModule {}
export { PermissionService } from './service';
export {
DOC_ACTIONS,
type DocActionPermissions,
type DocAction,
DocRole,
fixupDocRole,
mapDocRoleToPermissions,
mapWorkspaceRoleToPermissions,
PublicDocMode,
WORKSPACE_ACTIONS,
type WorkspaceActionPermissions,
type WorkspaceAction,
WorkspaceRole,
} from './types';

View File

@@ -146,12 +146,6 @@ type ResourceActionName<T extends keyof typeof Actions> =
export type WorkspaceAction = ResourceActionName<'Workspace'>;
export type DocAction = ResourceActionName<'Doc'>;
export type Action = WorkspaceAction | DocAction;
export type WorkspaceActionPermissions = {
[key in WorkspaceAction]: boolean;
};
export type DocActionPermissions = {
[key in DocAction]: boolean;
};
const cache = new WeakMap<object, any>();
const buildPathReader = (

View File

@@ -31,7 +31,7 @@ import { Models } from '../../../models';
import { CurrentUser } from '../../auth';
import {
DOC_ACTIONS,
type DocActionPermissions,
DocAction,
DocRole,
fixupDocRole,
mapDocRoleToPermissions,
@@ -41,6 +41,7 @@ import {
import { PublicUserType } from '../../user';
import { DocID } from '../../utils/doc';
import { WorkspaceType } from '../types';
import { DotToUnderline, mapPermissionToGraphqlPermissions } from './workspace';
registerEnumType(PublicDocMode, {
name: 'PublicDocMode',
@@ -128,10 +129,12 @@ class GrantedDocUserType {
@ObjectType()
class PaginatedGrantedDocUserType extends Paginated(GrantedDocUserType) {}
const DocPermissions = registerObjectType<DocActionPermissions>(
const DocPermissions = registerObjectType<
Record<DotToUnderline<DocAction>, boolean>
>(
Object.fromEntries(
DOC_ACTIONS.map(action => [
action,
action.replaceAll('.', '_'),
{
type: () => Boolean,
options: {
@@ -143,15 +146,6 @@ const DocPermissions = registerObjectType<DocActionPermissions>(
{ name: 'DocPermissions' }
);
@ObjectType()
export class DocRolePermissions {
@Field(() => DocRole)
role!: DocRole;
@Field(() => DocPermissions)
permissions!: DocActionPermissions;
}
@Resolver(() => WorkspaceType)
export class WorkspaceDocResolver {
private readonly logger = new Logger(WorkspaceDocResolver.name);
@@ -365,7 +359,7 @@ export class DocResolver {
async permissions(
@CurrentUser() user: CurrentUser,
@Parent() doc: DocType
): Promise<DocRolePermissions> {
): Promise<InstanceType<typeof DocPermissions>> {
const [permission, workspacePermission] = await this.prisma.$transaction(
tx =>
Promise.all([
@@ -385,12 +379,11 @@ export class DocResolver {
])
);
return {
role: permission?.type ?? DocRole.External,
permissions: mapDocRoleToPermissions(
return mapPermissionToGraphqlPermissions(
mapDocRoleToPermissions(
fixupDocRole(workspacePermission?.type, permission?.type)
),
};
)
);
}
@ResolveField(() => PaginatedGrantedDocUserType, {

View File

@@ -38,7 +38,7 @@ import {
mapWorkspaceRoleToPermissions,
PermissionService,
WORKSPACE_ACTIONS,
type WorkspaceActionPermissions,
WorkspaceAction,
WorkspaceRole,
} from '../../permission';
import { QuotaService, WorkspaceQuotaType } from '../../quota';
@@ -51,6 +51,22 @@ import {
} from '../types';
import { WorkspaceService } from './service';
export type DotToUnderline<T extends string> =
T extends `${infer Prefix}.${infer Suffix}`
? `${Prefix}_${DotToUnderline<Suffix>}`
: T;
export function mapPermissionToGraphqlPermissions<A extends string>(
permission: Record<A, boolean>
): Record<DotToUnderline<A>, boolean> {
return Object.fromEntries(
Object.entries(permission).map(([key, value]) => [
key.replaceAll('.', '_'),
value,
])
) as Record<DotToUnderline<A>, boolean>;
}
@ObjectType()
export class EditorType implements Partial<Editor> {
@Field()
@@ -75,10 +91,12 @@ class WorkspacePageMeta {
updatedBy!: EditorType | null;
}
const WorkspacePermissions = registerObjectType<WorkspaceActionPermissions>(
const WorkspacePermissions = registerObjectType<
Record<DotToUnderline<WorkspaceAction>, boolean>
>(
Object.fromEntries(
WORKSPACE_ACTIONS.map(action => [
action,
action.replaceAll('.', '_'),
{
type: () => Boolean,
options: {
@@ -96,7 +114,7 @@ export class WorkspaceRolePermissions {
role!: WorkspaceRole;
@Field(() => WorkspacePermissions)
permissions!: WorkspaceActionPermissions;
permissions!: Record<DotToUnderline<WorkspaceAction>, boolean>;
}
/**
@@ -342,7 +360,7 @@ export class WorkspaceResolver {
async workspaceRolePermissions(
@CurrentUser() user: CurrentUser,
@Args('id') id: string
) {
): Promise<WorkspaceRolePermissions> {
const workspace = await this.prisma.workspaceUserPermission.findFirst({
where: { workspaceId: id, userId: user.id },
});
@@ -351,7 +369,9 @@ export class WorkspaceResolver {
}
return {
role: workspace.type,
permissions: mapWorkspaceRoleToPermissions(workspace.type),
permissions: mapPermissionToGraphqlPermissions(
mapWorkspaceRoleToPermissions(workspace.type)
),
};
}