Skip to main content

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:

DecoratorWhat 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>';
}