Ґарди (охоронці)
Якщо ви хочете обмежити доступ до певних маршрутів, ви можете скористатись ґардами. Готовий приклад застосунку з ґардами ви можете проглянути у теці examples, або у RealWorld example.
Будь-який ґард є DI провайдером, що передається в інжектори на рівні запиту в injector-scope режимі, або на інших рівнях, якщо контролер працює в режимі context-scoped. Кожен ґард повинен бути класом, що впроваджує інтерфейс CanActivate:
interface CanActivate {
canActivate(ctx: RequestContext, params?: any[]): boolean | Response | Promise<boolean | Response>;
}
Наприклад, це можна зробити так:
import { guard, RequestContext, CanActivate } from '@ditsmod/rest';
import { AuthService } from './auth.service.js';
@guard()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService) {}
async canActivate(ctx: RequestContext, params?: any[]) {
return Boolean(await this.authService.updateAndGetSession());
}
}
Або так:
import { Status } from '@ditsmod/core';
import { RequestContext, CanActivate, guard } from '@ditsmod/rest';
import { AuthService } from './auth.service.js';
import { Permission } from './types.js';
@guard()
export class PermissionsGuard implements CanActivate {
constructor(private authService: AuthService) {}
async canActivate(ctx: RequestContext, params?: Permission[]) {
if (await this.authService.hasPermissions(params)) {
return true;
} else {
return new Response(null, { status: Status.FORBIDDEN });
}
}
}
Зверніть увагу, що ґарди можуть повертати інстанс стандартного класу Response.
Файли ґардів рекомендується називати із закінченням *.guard.ts, а імена їхніх класів - із закінченням *Guard.
Якщо canActivate() повертає:
trueчиPromise<true>, значить Ditsmod буде обробляти відповідний маршрут із цим ґардом;falseчиPromise<false>, значить відповідь на запит міститиме 401 статус і обробки маршруту з боку контролера не буде;- інстанс Response чи
Promise<Response>, які в даному контексті Ditsmod інтерпретує як відповідь на HTTP-запит.
Передача ґардів до інжекторів
Ґарди можна передавати у метадані модуля чи контролера:
import { restModule } from '@ditsmod/rest';
import { AuthGuard } from 'auth.guard';
@restModule({
providersPerReq: [AuthGuard],
})
export class SomeModule {}
В даному разі ґард буде працювати на рівні запиту, для контролерів в режимі injector-scoped.
Використання ґардів
Якщо ви використовуєте модуль @ditsmod/rest, ґарди передаються до контролерів в масиві у третьому параметрі декоратора route:
import { controller, Res, route } from '@ditsmod/rest';
import { AuthGuard } from './auth.guard.js';
@controller()
export class SomeController {
@route('GET', 'some-url', [AuthGuard])
tellHello(res: Res) {
res.send('Hello, admin!');
}
}