@jeonghochoi/rbac
v0.1.7
Published
Optional, async, multi-tenant RBAC module for NestJS
Readme
RBAC Module (NestJS)
Optional, Async, Multi-Tenant RBAC for NestJS
앱에 강제하지 않는 플러그인 형태의 RBAC (Role-Based Access Control) 모듈
✨ Features
- ✅ Optional RBAC
- Provider 미등록 시 자동 비활성화
- ✅ Async Permission Check
- DB / Redis / External API 기반 권한 검사 지원
- ✅ Multi-Tenant 지원
- tenantId 기반 role → permission 분리
- ✅ Decorator 기반 API 선언
- ✅ NestJS Guard 표준 구조
- ✅ Strict TypeScript / ESLint 호환
isolatedModules,no-unsafe-*대응
📦 Installation
npm install @jeonghochoi/rbac🧠 Core Concept
RBAC 모듈은 권한 데이터를 소유하지 않습니다.
| 역할 | 책임 | | ----------- | --------------------------------- | | RBAC 패키지 | 권한 검사 흐름 | | Application | tenant / role / permission 데이터 | | API | 요구 권한 선언 |
Provider가 없으면 RBAC는 아무 일도 하지 않습니다.
🔁 Request Flow
Request
→ @Public? → PASS
→ ContextProvider 없음? → PASS
→ PermissionChecker 없음? → PASS
→ @RequirePermissions 없음? → PASS
→ PermissionChecker.hasPermission (async)🧩 Decorators
@Public()
RBAC / Auth Guard를 모두 건너뜁니다.
@Public()
@Get('/health')
health() {}@RequirePermissions()
API 또는 Controller에 요구 권한을 선언합니다.
@RequirePermissions('user.read')
@Get('/users')
findUsers() {}@RequirePermissions('admin.access')
@Controller('/admin')
export class AdminController {}🔌 Interfaces
RbacContextProvider
export interface RbacContextProvider {
getContext(request: unknown): unknown;
}요청에서 사용자 / 테넌트 / 역할 정보를 추출
PermissionChecker
export interface PermissionChecker {
hasPermission(context: unknown, permission: string): Promise<boolean>;
}DB / Cache / 외부 시스템 기반 권한 검사
🛡 RbacGuard
RBAC Guard는 Global Guard 또는 Route Guard로 사용 가능합니다.
특징
- Provider 미존재 시 자동 스킵
- Async permission 검사 지원
- Strict TypeScript 대응
🔑 Tokens
export const RBAC_CONTEXT_PROVIDER_TOKEN = Symbol(
'RBAC_CONTEXT_PROVIDER_TOKEN',
);
export const PERMISSION_CHECKER_TOKEN = Symbol('PERMISSION_CHECKER_TOKEN');🧪 Example: Application Integration
1️⃣ ContextProvider 구현
@Injectable()
export class AppContextProvider implements RbacContextProvider {
getContext(req: Request): AppRequestContext {
return {
userId: req.user.id,
tenantId: req.user.tenantId,
roles: req.user.roles,
};
}
}2️⃣ PermissionChecker 구현 (Async)
@Injectable()
export class AppPermissionChecker implements PermissionChecker {
async hasPermission(
context: AppRequestContext,
permission: string,
): Promise<boolean> {
const { tenantId, roles } = context;
// Redis / DB / Cache 등
return this.repo.hasPermission(tenantId, roles, permission);
}
}3️⃣ AppModule 바인딩
@Module({
providers: [
{
provide: RBAC_CONTEXT_PROVIDER_TOKEN,
useClass: AppContextProvider,
},
{
provide: PERMISSION_CHECKER_TOKEN,
useClass: AppPermissionChecker,
},
],
})
export class AppModule {}⚠️ 위 Provider 중 하나라도 없으면 RBAC는 자동 비활성화됩니다.
🌍 Multi-Tenant RBAC
RBAC 모듈은 tenant 구조를 알지 못합니다.
context = {
tenantId,
roles,
};모든 tenant 별 권한 분리는 Application 책임입니다.
⚡ Performance Tips
- permission 단위 DB 조회 ❌
- role → permission 집합을 한 번에 조회 ✅
- Redis / Memory 캐시 적극 권장
- 권한 변경 시 cache invalidate
🧪 Testing
RBAC Provider 미등록 시 Guard는 항상 true를 반환합니다.
// TestModule
providers: [
RbacGuard, // ContextProvider / PermissionChecker 없음
];🚫 What This Module Does NOT Do
- ❌ DB 스키마 정의
- ❌ Role / Permission 관리 UI
- ❌ 권한 캐싱 전략
- ❌ Auth / JWT 처리
📌 When to Use
- SaaS / Multi-Tenant 서비스
- 점진적 RBAC 도입
- 마이크로서비스 일부만 RBAC 적용
- 테스트 / 배치 / 내부 API 분리
🏁 Summary
RBAC는 강제가 아니라 선택이다.
Provider를 등록하는 순간 활성화되고,
없으면 아무 일도 하지 않는다.
