Skip to content

Commit 92fd5c3

Browse files
committed
feat(authorization): make auth checker feature generic typed
1 parent 290ae5e commit 92fd5c3

File tree

14 files changed

+32
-28
lines changed

14 files changed

+32
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog and release notes
22

3+
## Unreleased
4+
### Features
5+
- make auth checker feature generic typed (default `string` for backward compatibility)
6+
37
## v0.11.2
48
### Features
59
- attach `MetadataStorage` to global scope (support multiple packages/modules)

docs/authorization.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class MyObject {
3232
```
3333

3434
You can leave the `@Authorized` decorator brackets empty or you can specify the roles that the user needs to have to get access to the field, query or mutation.
35+
By default the roles are `string` but you can change it easily as the decorator is generic - `@Authorized<number>(1, 7, 22)`.
3536

3637
This way authed users (regardless of theirs roles) could read only `publicField` or `authorizedField` from `MyObject` object. They will receive `null` when accessing `hiddenField` field and will receive error (that will propagate through the whole query tree looking for nullable field) for `adminField` when they don't satisfy roles constraints.
3738

@@ -74,6 +75,7 @@ export const customAuthChecker: AuthChecker<ContextType> =
7475
return true; // or false if access denied
7576
}
7677
```
78+
The second argument of `AuthChecker` generic type is `RoleType` - use it together with `@Authorized` decorator generic type.
7779

7880
The last step is to register the function while building the schema:
7981
```ts

src/decorators/Authorized.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { getMetadataStorage } from "../metadata/getMetadataStorage";
22
import { SymbolKeysNotSupportedError } from "../errors";
33
import { getArrayFromOverloadedRest } from "../helpers/decorators";
4+
import { MethodAndPropDecorator } from "../types/decorators";
45

5-
export type MethodOrPropDecorator = MethodDecorator & PropertyDecorator;
6-
7-
export function Authorized(): MethodOrPropDecorator;
8-
export function Authorized(roles: string[]): MethodOrPropDecorator;
9-
export function Authorized(...roles: string[]): MethodOrPropDecorator;
10-
export function Authorized(...rolesOrRolesArray: Array<string | string[]>): MethodOrPropDecorator {
6+
export function Authorized(): MethodAndPropDecorator;
7+
export function Authorized<RoleType = string>(roles: RoleType[]): MethodAndPropDecorator;
8+
export function Authorized<RoleType = string>(...roles: RoleType[]): MethodAndPropDecorator;
9+
export function Authorized<RoleType = string>(
10+
...rolesOrRolesArray: Array<RoleType | RoleType[]>
11+
): MethodDecorator | PropertyDecorator {
1112
const roles = getArrayFromOverloadedRest(rolesOrRolesArray);
1213

13-
return (prototype: object, propertyKey: string | symbol) => {
14+
return (prototype, propertyKey, descriptor) => {
1415
if (typeof propertyKey === "symbol") {
1516
throw new SymbolKeysNotSupportedError();
1617
}

src/decorators/Field.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { getMetadataStorage } from "../metadata/getMetadataStorage";
2-
import { ReturnTypeFunc, AdvancedOptions } from "../types/decorators";
2+
import { ReturnTypeFunc, AdvancedOptions, MethodAndPropDecorator } from "../types/decorators";
33
import { findType } from "../helpers/findType";
44
import { getTypeDecoratorParams } from "../helpers/decorators";
55
import { SymbolKeysNotSupportedError } from "../errors";
66

7-
export type MethodAndPropDecorator = PropertyDecorator & MethodDecorator;
8-
97
export function Field(options?: AdvancedOptions): MethodAndPropDecorator;
108
export function Field(
119
returnTypeFunction?: ReturnTypeFunc,

src/decorators/UseMiddleware.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import { SymbolKeysNotSupportedError } from "../errors";
22
import { Middleware } from "../interfaces/Middleware";
33
import { getMetadataStorage } from "../metadata/getMetadataStorage";
44
import { getArrayFromOverloadedRest } from "../helpers/decorators";
5+
import { MethodAndPropDecorator } from "../types/decorators";
56

6-
export function UseMiddleware(
7-
middlewares: Array<Middleware<any>>,
8-
): MethodDecorator & PropertyDecorator;
9-
export function UseMiddleware(
10-
...middlewares: Array<Middleware<any>>
11-
): MethodDecorator & PropertyDecorator;
7+
export function UseMiddleware(middlewares: Array<Middleware<any>>): MethodAndPropDecorator;
8+
export function UseMiddleware(...middlewares: Array<Middleware<any>>): MethodAndPropDecorator;
129
export function UseMiddleware(
1310
...middlewaresOrMiddlewareArray: Array<Middleware<any> | Array<Middleware<any>>>
1411
): MethodDecorator | PropertyDecorator {

src/helpers/auth-middleware.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { AuthChecker, AuthMode } from "../interfaces/auth-checker";
33
import { UnauthorizedError, ForbiddenError } from "../errors";
44

55
export function AuthMiddleware(
6-
authChecker: AuthChecker,
6+
authChecker: AuthChecker<any, any>,
77
authMode: AuthMode,
8-
roles: string[],
8+
roles: any[],
99
): MiddlewareFn {
1010
return async (action, next) => {
1111
const accessGranted = await authChecker(action, roles);

src/interfaces/auth-checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { ResolverData } from "../types/action-data";
22

3-
export type AuthChecker<ContextType = {}> = (
3+
export type AuthChecker<ContextType = {}, RoleType = string> = (
44
resolverData: ResolverData<ContextType>,
5-
roles: string[],
5+
roles: RoleType[],
66
) => boolean | Promise<boolean>;
77

88
export type AuthMode = "error" | "null";
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface AuthorizedMetadata {
22
target: Function;
33
fieldName: string;
4-
roles: string[];
4+
roles: any[];
55
}

src/metadata/definitions/field-metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ export interface FieldMetadata {
1010
description: string | undefined;
1111
deprecationReason: string | undefined;
1212
params?: ParamMetadata[];
13-
roles?: string[];
13+
roles?: any[];
1414
middlewares?: Array<Middleware<any>>;
1515
}

src/metadata/definitions/resolver-metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export interface BaseResolverMetadata {
1212
target: Function;
1313
handler: Function | undefined;
1414
params?: ParamMetadata[];
15-
roles?: string[];
15+
roles?: any[];
1616
middlewares?: Array<Middleware<any>>;
1717
}
1818

0 commit comments

Comments
 (0)