🏗️ Architecture

Guard System Deep Dive

NestJS guards used for authentication, authorization, and tenant isolation.

Guard Execution Order

Diagram; its source is available below
Diagram source
graph LR
    Request --> Global[Global Guards]
    Global --> Controller[Controller Guards]
    Controller --> Method[Method Guards]
    Method --> Handler[Route Handler]

Core Guards

TenantPermissionGuard

The most commonly used guard. Validates:

  1. User is authenticated (JWT valid)
  2. User belongs to the requested tenant
  3. User has required permissions
@UseGuards(TenantPermissionGuard)
@Permissions(PermissionsEnum.ORG_EMPLOYEES_VIEW)
@Get()
async findAll() {}

RoleGuard

Restricts access by user role:

@UseGuards(RoleGuard)
@Roles(RolesEnum.SUPER_ADMIN, RolesEnum.ADMIN)
@Delete(':id')
async delete(@Param('id') id: string) {}

PermissionGuard

Checks specific permissions:

@UseGuards(PermissionGuard)
@Permissions(PermissionsEnum.INVOICES_EDIT)
@Put(':id')
async update() {}

OrganizationPermissionGuard

Validates organization-level access:

@UseGuards(OrganizationPermissionGuard)
@Get()
async findByOrg() {}

Guard Hierarchy

GuardValidatesUsage
AuthGuard('jwt')JWT token validAll endpoints
TenantBaseGuardTenant exists in requestMost endpoints
TenantPermissionGuardTenant + permissionsCRUD operations
RoleGuardUser role matchesAdmin endpoints
PermissionGuardSpecific permissionFeature access
OrganizationPermissionGuardOrg membershipOrg endpoints

Creating Custom Guards

@Injectable()
export class ProjectMemberGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const projectId = request.params.projectId;
    const userId = request.user.id;

    return this.projectService.isMember(projectId, userId);
  }
}

Edit this page

Copyright © 2023-Present Ever Co. LTD.Docs by Sourcey