Skip to content

Commit

Permalink
Merge pull request #111 from getlarge/110-featketo-client-wrapper-all…
Browse files Browse the repository at this point in the history
…ow-dynamic-relationtuplecondition

feat(keto-client-wrapper): allow dynamic RelationTupleCondition
  • Loading branch information
getlarge authored Nov 12, 2024
2 parents 518e7b4 + b99ab01 commit 24adde3
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 26 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@nestjs/common": "^10.4.4",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.4.4",
"@ory/client": "^1.15.5",
"@ory/client": "^1.15.10",
"axios": "1.7.7",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/keto-client-wrapper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ export {
OryAuthorizationGuardOptions,
} from './lib/ory-authorization.guard';
export {
EnhancedRelationTupleFactory,
getOryPermissionChecks,
OryPermissionChecks,
RelationTupleCondition,
RelationTupleFactory,
} from './lib/ory-permission-checks.decorator';
export {
OryPermissionsModule,
Expand Down
13 changes: 9 additions & 4 deletions packages/keto-client-wrapper/src/lib/ory-authorization.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import { PermissionApiExpandPermissionsRequest } from '@ory/client';
import type { Observable } from 'rxjs';

import {
EnhancedRelationTupleFactory,
getOryPermissionChecks,
RelationTupleCondition,
RelationTupleFactory,
} from './ory-permission-checks.decorator';
import { OryPermissionsService } from './ory-permissions';

Expand All @@ -40,7 +41,7 @@ export abstract class IAuthorizationGuard implements CanActivate {
): boolean | Promise<boolean> | Observable<boolean>;

abstract evaluateConditions(
factory: EnhancedRelationTupleFactory,
factory: RelationTupleFactory | RelationTupleCondition,
context: ExecutionContext
): Promise<{
allowed: boolean;
Expand Down Expand Up @@ -72,7 +73,7 @@ export const OryAuthorizationGuard = (
}

async evaluateConditions(
factory: EnhancedRelationTupleFactory,
factory: RelationTupleFactory | RelationTupleCondition,
context: ExecutionContext
): Promise<{
allowed: boolean;
Expand Down Expand Up @@ -138,7 +139,11 @@ export const OryAuthorizationGuard = (
return true;
}
const { postCheck, unauthorizedFactory } = this.options;
for (const factory of factories) {
for (const firstLevelFactory of factories) {
const factory =
typeof firstLevelFactory === 'function'
? firstLevelFactory(context)
: firstLevelFactory;
const { allowed, relationTuple } = await this.evaluateConditions(
factory,
context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export type RelationTupleCondition = {

export type EnhancedRelationTupleFactory =
| RelationTupleFactory
| RelationTupleCondition;
| RelationTupleCondition
| ((ctx: ExecutionContext) => RelationTupleCondition);

/**
* @description Decorator to add permission checks to a handler, will be consumed by the `OryAuthorizationGuard` {@link OryAuthorizationGuard} using the `getOryPermissionChecks` {@link getOryPermissionChecks} function
Expand Down
28 changes: 12 additions & 16 deletions packages/keto-client-wrapper/test/app.controller.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,21 @@ export class ExampleController {
return this.exampleService.getExample();
}

@OryPermissionChecks({
type: 'OR',
conditions: [
(ctx) => {
const req = ctx.switchToHttp().getRequest();
const resourceId = req.params.id;
return `Toy:${resourceId}#owners`;
},
(ctx) => {
const req = ctx.switchToHttp().getRequest();
const currentUserId = req.headers['x-current-user-id'] as string;
const resourceId = req.params.id;
return new RelationTupleBuilder()
@OryPermissionChecks((ctx) => {
const req = ctx.switchToHttp().getRequest();
const resourceId = req.params.id;
const currentUserId = req.headers['x-current-user-id'] as string;
return {
type: 'OR',
conditions: [
`Toy:${resourceId}#owners`,
new RelationTupleBuilder()
.subject('User', currentUserId)
.isIn('owners')
.of('Toy', resourceId)
.toString();
},
],
.toString(),
],
};
})
@UseGuards(AuthorizationGuard())
@Get('poly/:id')
Expand Down

0 comments on commit 24adde3

Please sign in to comment.