Guards
Guards determine whether a request should be handled by the route handler.
Guards execute before the route handler and decide if the request should proceed. They implement the CanActivate interface and return a boolean indicating whether access is granted.
CanActivate Interface
import { Injectable, CanActivate, ExecutionContext } from '@velajs/vela';
@Injectable()
class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean | Promise<boolean> {
const request = context.getRequest();
const token = request.headers.get('authorization');
return !!token;
}
}Execution Context
The ExecutionContext provides details about the current request pipeline:
| Method | Description |
|---|---|
getClass() | Returns the controller class |
getHandler() | Returns the route handler method |
getContext<T>() | Returns the platform-specific context |
getRequest() | Returns the incoming request object |
Binding Guards
Apply guards at the method or controller level with @UseGuards():
import { Controller, Get, UseGuards } from '@velajs/vela';
@Controller('spirits')
@UseGuards(AuthGuard)
class SpiritsController {
@Get()
findAll() {
return [];
}
@Get('admin')
@UseGuards(RolesGuard)
adminOnly() {
return { admin: true };
}
}Global Guards
Register guards globally so they run on every route:
const app = await VelaFactory.create(AppModule);
app.useGlobalGuards(new AuthGuard());Or use the APP_GUARD injection token to register them through the module system with full dependency injection:
import { APP_GUARD } from '@velajs/vela';
@Module({
providers: [
{
provide: APP_GUARD,
useClass: AuthGuard,
},
],
})
class AppModule {}Resolution Order
Guards execute in order: global → controller → handler. If any guard returns false, the framework throws a ForbiddenException and the request is rejected immediately.
Role-Based Authorization
A common pattern is restricting routes based on user roles. Use SetMetadata to attach role requirements and Reflector to read them in a guard:
import { SetMetadata } from '@velajs/vela';
const Roles = (...roles: string[]) => SetMetadata('roles', roles);import {
Injectable, CanActivate, ExecutionContext,
Reflector, ForbiddenException,
} from '@velajs/vela';
@Injectable()
class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext) {
const roles = this.reflector.get<string[]>('roles', context);
if (!roles) return true;
const request = context.getRequest();
const userRole = request.headers.get('x-role');
if (!roles.includes(userRole)) {
throw new ForbiddenException('Insufficient role');
}
return true;
}
}Apply the roles decorator to routes:
@Controller('spirits')
@UseGuards(RolesGuard)
class SpiritsController {
@Get()
findAll() {
return [];
}
@Post()
@Roles('admin')
create(@Body() body: { name: string }) {
return body;
}
}Dependency Injection
Vela's IoC container provides automatic constructor injection with support for scopes and custom tokens.
Pipes
Pipes transform and validate input data before it reaches the route handler.
Last updated on