Skip to content

Commit 7bd4855

Browse files
committed
🛂 Introduce @Permission decorator
This decorator can accept permission conditions required to access the resource. For example: ``` @Permission(({ args }) => Promise.resolve({ or: [ { type: 'global', permission: P.global.VIEW_ANY_PLAN_DATA }, { type: 'plan', permission: P.plan.VIEW_DATA, id: args.id }, ], }) ) ``` If only global permission check is needed, it can be used directly: ``` @Permission({ type: 'global', permission: P.global.VIEW_ALL_JOBS, }) ```
1 parent e468c45 commit 7bd4855

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { actionIsPermitted } from '@unocha/hpc-api-core/src/auth';
2+
import { RequiredPermissionsCondition } from '@unocha/hpc-api-core/src/auth/permissions';
3+
import { Context } from '@unocha/hpc-api-core/src/lib/context';
4+
import { ForbiddenError } from '@unocha/hpc-api-core/src/util/error';
5+
import { createMethodDecorator, ResolverData } from 'type-graphql';
6+
7+
type RequiredPermissions = (
8+
resolverData: ResolverData<Context>
9+
) => Promise<RequiredPermissionsCondition<never>>;
10+
11+
// eslint-disable-next-line @typescript-eslint/naming-convention
12+
export function Permission(
13+
requiredPermissions: RequiredPermissions | RequiredPermissionsCondition<never>
14+
): MethodDecorator {
15+
return createMethodDecorator(
16+
async (resolverData: ResolverData<Context>, next) => {
17+
let permissions: RequiredPermissionsCondition<never>;
18+
if (typeof requiredPermissions === 'function') {
19+
permissions = await requiredPermissions(resolverData);
20+
} else {
21+
permissions = requiredPermissions;
22+
}
23+
24+
if (!(await actionIsPermitted(permissions, resolverData.context))) {
25+
throw new ForbiddenError('No permission to perform this action');
26+
}
27+
28+
return next();
29+
}
30+
);
31+
}

0 commit comments

Comments
 (0)