Package Exports
- exguard-backend
Readme
ExGuard Backend SDK
Simple RBAC permission guard for NestJS.
Installation
npm install exguard-backendQuick Setup (Auto)
Run this command in your NestJS project root:
npx exguard-backend setupThis creates:
src/exguard/exguard.guard.ts- The permission guardsrc/exguard/exguard.module.ts- The module
Manual Setup
1. Create Guard File
src/exguard/exguard.guard.ts:
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException, ForbiddenException, Inject, Optional } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ExGuardBackend } from 'exguard-backend';
export const EXGUARD_PERMISSIONS_KEY = 'exguard_permissions';
export const EXGUARD_ROLES_KEY = 'exguard_roles';
@Injectable()
export class ExGuardPermissionGuard implements CanActivate {
constructor(
@Optional() @Inject('EXGUARD_INSTANCE') private exGuard: ExGuardBackend,
private reflector: Reflector,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractToken(request);
if (!token) throw new UnauthorizedException('No token provided');
if (!this.exGuard) return true;
const authResult = await this.exGuard.authenticate({ token, request });
if (!authResult.allowed) throw new ForbiddenException(authResult.error || 'Access denied');
if (!authResult.user) throw new ForbiddenException('User not found');
const permMeta = this.reflector.get(EXGUARD_PERMISSIONS_KEY, context.getHandler());
if (permMeta) {
const userPermissions = authResult.user.modules?.flatMap(m => m.permissions) || [];
const hasPermission = permMeta.requireAll
? permMeta.permissions.every(p => userPermissions.includes(p))
: permMeta.permissions.some(p => userPermissions.includes(p));
if (!hasPermission) throw new ForbiddenException('Insufficient permissions');
}
request.user = authResult.user;
return true;
}
private extractToken(request: any): string | null {
const auth = request.headers?.authorization;
return auth?.startsWith('Bearer ') ? auth.substring(7) : null;
}
}
export function RequirePermissions(permissions: string[], requireAll = false): any {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
Reflect.defineMetadata(EXGUARD_PERMISSIONS_KEY, { permissions, requireAll }, descriptor.value);
return descriptor;
};
}2. Create Module File
src/exguard/exguard.module.ts:
import { Module, Global, DynamicModule } from '@nestjs/common';
import { ExGuardBackend } from 'exguard-backend';
@Global()
@Module({})
export class ExGuardModule {
static forRoot(options: { baseUrl: string; apiKey: string; cache?: { enabled?: boolean; ttl?: number } }): DynamicModule {
const exGuard = new ExGuardBackend({
baseUrl: options.baseUrl,
apiKey: options.apiKey,
cache: options.cache || { enabled: true, ttl: 300000 },
});
return {
module: ExGuardModule,
providers: [{ provide: 'EXGUARD_INSTANCE', useValue: exGuard }],
exports: ['EXGUARD_INSTANCE'],
};
}
}3. Configure AppModule
import { Module } from '@nestjs/common';
import { ExGuardModule } from './exguard/exguard.module';
@Module({
imports: [
ExGuardModule.forRoot({
baseUrl: 'https://api.exguard.com',
apiKey: process.env.EXGUARD_API_KEY,
}),
],
})
export class AppModule {}4. Use in Controllers
import { Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ExGuardPermissionGuard, RequirePermissions } from '@/exguard/exguard.guard';
@Controller('items')
@UseGuards(ExGuardPermissionGuard)
export class ItemsController {
// User needs ANY of these permissions
@Get()
@RequirePermissions(['item:read'])
findAll() { }
@Post()
@RequirePermissions(['item:create'])
create() { }
// Multiple permissions - needs ALL
@Delete(':id')
@RequirePermissions(['item:delete', 'admin'], true)
delete() { }
}API Reference
| Decorator | Description |
|---|---|
@RequirePermissions(['perm1']) |
User needs ANY of the permissions |
@RequirePermissions(['perm1', 'perm2'], true) |
User needs ALL permissions |
Token
The guard extracts token from:
Authorization: Bearer <token>headerx-access-tokenheader
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
| baseUrl | string | required | ExGuard API URL |
| apiKey | string | required | Your API key |
| cache.enabled | boolean | true | Enable caching |
| cache.ttl | number | 300000 | Cache TTL (5 min) |
Express/Fastify (Non-NestJS)
import { createExGuardExpress } from 'exguard-backend';
const guard = createExGuardExpress({
baseUrl: 'https://api.exguard.com',
apiKey: process.env.EXGUARD_API_KEY,
});
app.use('/api', guard.requirePermissions(['item:read']));License
MIT