Lifecycle & Validation
Every request runs through a fixed pipeline before your handler executes, and again afterward before the response goes out:
auth strategies → @RequiresElevation → @RequiresTrustedRole → @RequiresRole → @RequiresScope → ACL check → @Validate → @Before → handler → @After
Each stage can reject the request before the next one runs, and before your handler ever sees it, a thrown error at any point turns into a response the same way a thrown error in the handler itself would, see Error Handling. Authentication strategies and the ACL permission check are covered in Authentication & Authorization.
Guard decorators
These gate access to a handler before it runs, in the order shown above:
| Decorator | What it does |
|---|---|
@RequiresElevation(seconds?) | Requires a recently confirmed elevated session (a re-authentication step), within the last seconds. Omit it and elevation just needs to still be active. |
@RequiresTrustedRole() | Requires the user to have at least one role marked trusted. |
@RequiresRole(roles) | Requires the user to have at least one of the given role(s). |
@RequiresScope(scopes) | Requires the token to carry at least one of the given OAuth-style scope(s), a coarse, token-level check that runs before the per-resource ACL check. |
@Validate(func)
Runs a validation function before the handler. Throw to reject the request with a 400:
@Post()
@Validate('validateCreate')
async createPet(pet: Pet) {
return this.petService.create(pet);
}
private validateCreate(pet: Pet) {
if (!pet.name) throw new Error('name is required');
}
func is a function reference or the string name of a method on the same class, not an array, one validator per handler.
@Before(func) / @After(func)
Run one or more functions immediately before or after the handler. Both accept a single function/name or an array of them:
@Get('/:id')
@After('cleanPII')
async findById(@Param('id') id: string, @User user?: JWTUser) {
return super.findById(id);
}
private cleanPII(pet: Pet, @User user?: JWTUser) {
if (!user) pet.ownerContact = undefined;
return pet;
}
@After is the standard way to post-process a response, stripping fields a caller isn't authorized to see, adding computed fields, without duplicating the handler that produced the data.
@ContentType(type)
Overrides the response content-type (JSON is the default):
@Get()
@ContentType('text/html')
getHtml(): string {
return '<h1>Hello</h1>';
}