Read models' before hooks
With this new version, we can now add before
hooks to our @ReadModel annotations. This can become really handy to either:
- Validate parameters
- Change read model filters on the fly with programmatic logic
- Deny access to specific users
For example, we could deny user's access when he/she's not the Cart's owner:
@ReadModel({
authorize: [User],
before: [validateUser],
})
export class CartReadModel {
public constructor(
readonly id: UUID,
readonly userId: UUID
) {}
// Your projections go here
}
function validateUser(filter: FilterFor<CartReadModel>, currentUser?: UserEnvelope): FilterFor<CartReadModel> {
if (filter?.userId !== currentUser.id) throw NotAuthorizedError("...")
return filter
}
You can also chain these before functions to split your logic:
import { changeFilters } from '../../filters-helper' // You can also use external functions!
@ReadModel({
authorize: [User],
before: [validateUser, validateEmail, changeFilters],
})
export class CartReadModel {
public constructor(
readonly id: UUID,
readonly userId: UUID
) {}
// Your projections go here
}
function validateUser(filter: FilterFor<CartReadModel>, currentUser?: UserEnvelope): FilterFor<CartReadModel> {
if (filter.userId !== currentUser.id) throw NotAuthorizedError("...")
return filter // This filter will be passed as a parameter to the validateEmail function
}
function validateEmail(filter: FilterFor<CartReadModel>, currentUser?: UserEnvelope): FilterFor<CartReadModel> {
if (!filter.email.includes('myCompanyDomain.com')) throw NotAuthorizedError("...")
return filter
}
As a side note, remember that the order in which filters are specified matters.