@lark-apaas/nestjs-authzpaas 0.1.0-alpha.0 → 0.1.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import { DynamicModule, Type, CanActivate, ExecutionContext, NestMiddleware, HttpException, ExceptionFilter, ArgumentsHost } from '@nestjs/common';
2
- import { Reflector } from '@nestjs/core';
1
+ import { DynamicModule, Type, HttpException } from '@nestjs/common';
3
2
  import { PureAbility } from '@casl/ability';
4
- import { Request, Response, NextFunction } from 'express';
5
3
 
6
4
  /**
7
5
  * 用户角色
@@ -38,7 +36,6 @@ interface UserPermissionData {
38
36
  /** 用户角色列表 */
39
37
  roles: string[];
40
38
  /** 用户权限点位列表 */
41
- permissions: Permission[];
42
39
  /** 数据获取时间 */
43
40
  fetchedAt: Date;
44
41
  }
@@ -82,28 +79,33 @@ type Action = 'create' | 'read' | 'update' | 'delete' | 'manage' | string;
82
79
  */
83
80
  type Subject = string | object;
84
81
  /**
85
- * 缓存配置
82
+ * 获取用户角色数据
86
83
  */
87
- interface CacheConfig {
88
- /** 缓存过期时间(秒),默认 300 */
89
- ttl?: number;
90
- /** 最大缓存数量,默认 1000 */
91
- max?: number;
92
- /** 是否启用缓存,默认 true */
93
- enabled?: boolean;
84
+ interface UserRolesDTO {
85
+ /** 基础 URL */
86
+ baseUrl: string;
87
+ /** 用户ID */
88
+ userId: string;
89
+ /** 应用ID */
90
+ appId: string;
91
+ /** cookies 字符串 */
92
+ cookies: Record<string, string>;
93
+ /** CSRF 令牌 */
94
+ csrfToken: string;
95
+ }
96
+ interface UserContext {
97
+ userId?: string;
98
+ tenantId?: number;
99
+ appId?: string;
100
+ userRoles?: string[];
101
+ baseUrl?: string;
102
+ cookies?: Record<string, string>;
103
+ csrfToken?: string;
94
104
  }
95
105
  /**
96
106
  * 权限 API 配置
97
107
  */
98
108
  interface PermissionApiConfig {
99
- /** 权限 API 基础 URL */
100
- baseUrl: string;
101
- /** API 认证 Token(可选) */
102
- apiToken?: string;
103
- /** 权限的端点路径 */
104
- endpoint: string;
105
- /** 自定义请求头 */
106
- headers?: Record<string, string>;
107
109
  /** 请求超时时间(毫秒),默认 5000 */
108
110
  timeout?: number;
109
111
  }
@@ -113,23 +115,12 @@ interface PermissionApiConfig {
113
115
  interface AuthZPaasModuleOptions {
114
116
  /** 权限 API 配置 */
115
117
  permissionApi?: PermissionApiConfig;
116
- /** 缓存配置 */
117
- cache?: CacheConfig;
118
- /** 是否启用 mock 角色功能,默认 false */
119
- enableMockRole?: boolean;
120
- /** 是否总是需要登录,默认 true */
121
- alwaysNeedLogin?: boolean;
122
- /** 未登录时默认重定向的登录页路径(可被 @NeedLogin 覆盖),默认 '/login' */
123
- loginPath?: string;
124
- /** 是否全局模块,默认 true */
125
- isGlobal?: boolean;
126
118
  }
127
119
 
128
120
  interface AuthZPaasModuleAsyncOptions {
129
121
  imports?: Type<unknown>[];
130
122
  inject?: (string | symbol | Type<unknown>)[];
131
123
  useFactory: (...args: unknown[]) => Promise<AuthZPaasModuleOptions> | AuthZPaasModuleOptions;
132
- isGlobal?: boolean;
133
124
  }
134
125
  declare class AuthZPaasModule {
135
126
  static forRoot(options: AuthZPaasModuleOptions): DynamicModule;
@@ -192,337 +183,6 @@ type CheckRoleRequirement = RoleRequirement;
192
183
  */
193
184
  declare const CanRole: (role: string[] | string, and?: boolean) => MethodDecorator;
194
185
 
195
- /**
196
- * 权限要求配置
197
- */
198
- interface PermissionRequirement {
199
- /** 操作类型 */
200
- actions: Action[];
201
- /** 资源类型 */
202
- subject: Subject;
203
- /** 是否需要所有操作(AND),默认 true(AND) */
204
- or?: boolean;
205
- }
206
- /**
207
- * 要求用户拥有指定权限
208
- *
209
- * @example
210
- * ```typescript
211
- * // 通过 CASL 动作和资源检查(推荐使用)
212
- * @CanPermission({ actions: ['create'], subject: 'User' })
213
- * async createUser() {}
214
- *
215
- * @CanPermission({ actions: ['update'], subject: 'Article' })
216
- * async updateArticle() {}
217
- *
218
- * @CanPermission({ actions: ['delete'], subject: 'Comment' })
219
- * async deleteComment() {}
220
- *
221
- * // 注意:基于权限名称列表的检查方式暂不支持
222
- * // permissions 参数暂时保留用于未来扩展
223
- * ```
224
- */
225
- declare const CanPermission: (permission: PermissionRequirement[] | PermissionRequirement, or?: boolean) => MethodDecorator;
226
-
227
- /**
228
- * 网络要求
229
- */
230
- interface NetworkRequirement {
231
- /** 允许的 IP 地址列表(支持 CIDR) */
232
- allowedIPs?: string[];
233
- /** 禁止的 IP 地址列表 */
234
- blockedIPs?: string[];
235
- /** 允许的地区列表 */
236
- allowedRegions?: string[];
237
- }
238
- /**
239
- * 设备要求
240
- */
241
- interface DeviceRequirement {
242
- /** 允许的设备类型 */
243
- types?: Array<'mobile' | 'desktop' | 'tablet'>;
244
- /** 允许的操作系统 */
245
- os?: string[];
246
- /** 允许的浏览器 */
247
- browsers?: string[];
248
- }
249
- /**
250
- * 环境要求配置
251
- */
252
- interface EnvironmentRequirement {
253
- /** 网络要求 */
254
- network?: NetworkRequirement;
255
- /** 设备要求 */
256
- device?: DeviceRequirement;
257
- /** 自定义环境验证函数 */
258
- custom?: (context: any) => boolean | Promise<boolean>;
259
- }
260
- /**
261
- * 要求特定的环境条件
262
- *
263
- * @example
264
- * ```typescript
265
- * // 仅允许桌面端访问
266
- * @CanEnv({ device: { types: ['desktop'] } })
267
- * async adminPanel() {}
268
- *
269
- * // 限制 IP 访问
270
- * @CanEnv({
271
- * network: {
272
- * allowedIPs: ['192.168.1.0/24', '10.0.0.1']
273
- * }
274
- * })
275
- * async internalAPI() {}
276
- *
277
- * // 自定义验证
278
- * @CanEnv({
279
- * custom: (ctx) => ctx.headers['x-api-key'] === 'secret'
280
- * })
281
- * async secretEndpoint() {}
282
- * ```
283
- */
284
- declare const CanEnv: (requirement: EnvironmentRequirement) => MethodDecorator;
285
-
286
- /**
287
- * 获取当前用户 ID
288
- *
289
- * @example
290
- * ```typescript
291
- * @Get('profile')
292
- * getProfile(@UserId() userId: string) {
293
- * return { userId };
294
- * }
295
- * ```
296
- */
297
- declare const UserId: (...dataOrPipes: unknown[]) => ParameterDecorator;
298
-
299
- declare const MockRoles: (...dataOrPipes: unknown[]) => ParameterDecorator;
300
-
301
- /**
302
- * CASL Ability 类型
303
- */
304
- type AppAbility = PureAbility<[Action, Subject]>;
305
- /**
306
- * 角色检查的特殊 Subject
307
- * 用于统一角色鉴权和权限点位鉴权
308
- *
309
- * 使用方式:
310
- * - 权限点位鉴权:ability.can('read', 'Todo')
311
- * - 角色鉴权:ability.can('admin', ROLE_SUBJECT) 或 ability.can('admin', '@role')
312
- */
313
- declare const ROLE_SUBJECT = "@role";
314
- /**
315
- * Ability 工厂
316
- * 负责根据用户权限数据创建 CASL Ability 实例
317
- *
318
- * 统一了两种鉴权方式:
319
- * 1. 基于角色的鉴权 - 角色名作为 action,'@role' 作为 subject
320
- * 2. 基于权限点位的鉴权 - 标准的 action + subject 模式
321
- */
322
- declare class AbilityFactory {
323
- /**
324
- * 为用户创建 Ability
325
- */
326
- createForUser(permissionData: UserPermissionData): AppAbility;
327
- }
328
-
329
- interface CheckPermissionsParams {
330
- requirements: PermissionRequirement[];
331
- or?: boolean;
332
- }
333
- /**
334
- * 权限服务
335
- * 内置权限获取和缓存逻辑,以及权限检查逻辑
336
- */
337
- declare class PermissionService {
338
- private readonly apiConfig;
339
- private readonly abilityFactory;
340
- private readonly logger;
341
- private readonly cache;
342
- private readonly pendingRequests;
343
- constructor(apiConfig: PermissionApiConfig, cacheConfig: CacheConfig, abilityFactory: AbilityFactory);
344
- /**
345
- * 构建权限/Ability 缓存 key
346
- * - 若存在模拟角色:按角色集合排序拼接 + 用户维度
347
- * - 否则按 userId/匿名用户
348
- */
349
- private buildCacheKey;
350
- /**
351
- * 获取用户权限数据(带缓存)
352
- */
353
- getUserPermissions(userId?: string, mockRoles?: string[]): Promise<UserPermissionData | null>;
354
- /**
355
- * 从 API 获取权限数据
356
- * 内置实现,用户无需配置
357
- */
358
- private fetchFromApi;
359
- /**
360
- * 基于模拟角色获取权限数据(不使用缓存)
361
- * 该方法用于前端/守卫在检测到 mockRoles 时直接按角色获取权限
362
- */
363
- getPermissionsByMockRoles(userId: string | undefined, mockRoles: string[]): Promise<UserPermissionData>;
364
- /**
365
- * 获取用户的 Ability 实例(带缓存)
366
- * @param userId 用户ID
367
- * @returns CASL Ability 实例
368
- */
369
- private getUserAbility;
370
- /**
371
- * 清除用户权限缓存
372
- */
373
- clearUserCache(userId: string): void;
374
- /**
375
- * 清除所有缓存
376
- */
377
- clearAllCache(): void;
378
- /**
379
- * 获取缓存统计信息
380
- */
381
- getCacheStats(): {
382
- size: number;
383
- hits: number;
384
- misses: number;
385
- hitRate: number;
386
- enabled: boolean;
387
- };
388
- /**
389
- * 检查角色要求
390
- * 使用 CASL Ability 统一鉴权方式
391
- * @param requirement 角色要求
392
- * @param userId 用户ID,匿名用户时为空
393
- * @returns 用户权限数据
394
- * @throws PermissionDeniedException 当角色不满足时
395
- */
396
- checkRoles(requirement: RoleRequirement, userId?: string, mockRoles?: string[]): Promise<UserPermissionData>;
397
- /**
398
- * 检查权限要求
399
- * @param requirements 权限要求列表
400
- * @param userId 用户ID
401
- * @returns 用户权限数据
402
- * @throws PermissionDeniedException 当权限不满足时
403
- */
404
- checkPermissions(params: CheckPermissionsParams, userId?: string, mockRoles?: string[]): Promise<UserPermissionData>;
405
- getAbility(userId: string): Promise<AppAbility>;
406
- }
407
-
408
- /**
409
- * AuthZPaas 守卫
410
- * 负责协调所有鉴权检查,具体检查逻辑委托给 PermissionService
411
- */
412
- declare class AuthZPaasGuard implements CanActivate {
413
- private reflector;
414
- private permissionService;
415
- private moduleOptions;
416
- constructor(reflector: Reflector, permissionService: PermissionService, moduleOptions: AuthZPaasModuleOptions);
417
- canActivate(context: ExecutionContext): Promise<boolean>;
418
- /**
419
- * 从请求中提取用户ID
420
- * 子类可以重写此方法以适应不同的认证策略
421
- */
422
- protected extractUserId(request: {
423
- userContext?: {
424
- userId?: string;
425
- };
426
- cookies?: Record<string, string | undefined>;
427
- }): string | undefined;
428
- /**
429
- * 从请求中提取环境上下文
430
- */
431
- protected extractEnvironmentContext(request: {
432
- ip?: string;
433
- connection?: {
434
- remoteAddress?: string;
435
- };
436
- headers: Record<string, string | string[] | undefined>;
437
- query?: Record<string, unknown>;
438
- }): EnvironmentContext;
439
- /**
440
- * 检测设备类型
441
- */
442
- private detectDeviceType;
443
- /**
444
- * 检查角色要求
445
- */
446
- private checkRoleRequirement;
447
- /**
448
- * 检查权限要求
449
- */
450
- private checkPermissionRequirement;
451
- /**
452
- * 检查环境要求
453
- */
454
- private checkEnvironmentRequirement;
455
- /**
456
- * 检查网络要求
457
- */
458
- private checkNetworkRequirement;
459
- /**
460
- * 检查设备要求
461
- */
462
- private checkDeviceRequirement;
463
- /**
464
- * 检查 IP 是否匹配
465
- * 简化版本,仅支持精确匹配
466
- * 生产环境建议使用 ipaddr.js 等库
467
- */
468
- private checkIPMatch;
469
- }
470
-
471
- /**
472
- * 常量
473
- */
474
- /** 匿名用户 ID */
475
- declare const ANONYMOUS_USER_ID = "anonymous_user_id";
476
- /**
477
- * 依赖注入 Token
478
- */
479
- /** 权限 API 配置 Token */
480
- declare const PERMISSION_API_CONFIG_TOKEN: unique symbol;
481
- /** 缓存配置 Token */
482
- declare const CACHE_CONFIG_TOKEN: unique symbol;
483
- /** AuthZPaas 模块选项 Token */
484
- declare const AUTHZPAAS_MODULE_OPTIONS: unique symbol;
485
- /**
486
- * 元数据键
487
- */
488
- /** 需要的角色元数据键 */
489
- declare const ROLES_KEY = "authzpaas:roles";
490
- /** 需要的权限元数据键 */
491
- declare const PERMISSIONS_KEY = "authzpaas:permissions";
492
- /** 需要的环境元数据键 */
493
- declare const ENVIRONMENT_KEY = "authzpaas:environment";
494
- /** 需要登录元数据键 */
495
- declare const NEED_LOGIN_KEY = "authzpaas:needLogin";
496
- /** 模块选项:登录页路径默认值 */
497
- declare const DEFAULT_LOGIN_PATH = "/login";
498
- /** 角色模拟的 Cookie 键名 */
499
- declare const MOCK_ROLES_COOKIE_KEY = "mockRoles";
500
- declare const ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
501
-
502
- interface UserContext {
503
- userId?: string;
504
- tenantId?: number;
505
- appId?: string;
506
- userRoles?: string[];
507
- }
508
- /**
509
- * 扩展 Express Request 类型,添加用户权限相关字段
510
- */
511
- declare global {
512
- namespace Express {
513
- interface Request {
514
- userContext: UserContext;
515
- [ENABLE_MOCK_ROLE_KEY]?: boolean;
516
- }
517
- }
518
- }
519
- declare class RolesMiddleware implements NestMiddleware {
520
- private readonly permissionService;
521
- private readonly logger;
522
- constructor(permissionService: PermissionService);
523
- use(req: Request, _res: Response, next: NextFunction): Promise<void>;
524
- }
525
-
526
186
  /**
527
187
  * 权限拒绝异常类型
528
188
  */
@@ -533,8 +193,6 @@ declare enum PermissionDeniedType {
533
193
  ROLE_REQUIRED = "ROLE_REQUIRED",
534
194
  /** 缺少权限 */
535
195
  PERMISSION_REQUIRED = "PERMISSION_REQUIRED",
536
- /** 环境不满足 */
537
- ENVIRONMENT_REQUIRED = "ENVIRONMENT_REQUIRED",
538
196
  /** 权限配置查询失败 */
539
197
  PERMISSION_CONFIG_QUERY_FAILED = "PERMISSION_CONFIG_QUERY_FAILED"
540
198
  }
@@ -558,7 +216,7 @@ interface PermissionDeniedDetails {
558
216
  /** 环境要求(如果适用) */
559
217
  environmentRequirement?: string;
560
218
  /** 额外信息 */
561
- metadata?: Record<string, any>;
219
+ metadata?: Record<string, unknown>;
562
220
  }
563
221
  /**
564
222
  * 权限拒绝异常
@@ -583,91 +241,65 @@ declare class PermissionDeniedException extends HttpException {
583
241
  actions: string[];
584
242
  subject: string;
585
243
  }>, or?: boolean, customMessage?: string): PermissionDeniedException;
586
- /**
587
- * 创建环境不满足异常
588
- */
589
- static environmentRequired(requirement: string, message?: string): PermissionDeniedException;
590
244
  }
591
245
 
592
246
  /**
593
- * AuthZPaas 异常过滤器
594
- * 确保权限错误信息能够正确返回给客户端
247
+ * CASL Ability 类型
248
+ */
249
+ type AppAbility = PureAbility<[Action, Subject]>;
250
+ /**
251
+ * 角色检查的特殊 Subject
252
+ * 用于统一角色鉴权和权限点位鉴权
253
+ *
254
+ * 使用方式:
255
+ * - 权限点位鉴权:ability.can('read', 'Todo')
256
+ * - 角色鉴权:ability.can('admin', ROLE_SUBJECT) 或 ability.can('admin', '@role')
257
+ */
258
+ declare const ROLE_SUBJECT = "@role";
259
+ /**
260
+ * Ability 工厂
261
+ * 负责根据用户权限数据创建 CASL Ability 实例
262
+ *
263
+ * 统一了两种鉴权方式:
264
+ * 1. 基于角色的鉴权 - 角色名作为 action,'@role' 作为 subject
265
+ * 2. 基于权限点位的鉴权 - 标准的 action + subject 模式
595
266
  */
596
- declare class AuthZPaasExceptionFilter implements ExceptionFilter {
597
- catch(exception: PermissionDeniedException, host: ArgumentsHost): void;
267
+ declare class AbilityFactory {
268
+ /**
269
+ * 为用户创建 Ability
270
+ */
271
+ createForUser(permissionData: UserPermissionData): AppAbility;
598
272
  }
599
273
 
600
274
  /**
601
- * 权限数据 DTO
275
+ * 常量
602
276
  */
603
- declare class PermissionDto {
604
- sub: string;
605
- actions: string[];
606
- id?: string;
607
- name?: string;
608
- conditions?: Record<string, unknown>;
609
- }
277
+ /** 匿名用户 ID */
278
+ declare const ANONYMOUS_USER_ID = "anonymous_user_id";
610
279
  /**
611
- * 权限查询响应
280
+ * 依赖注入 Token
612
281
  */
613
- declare class PermissionResponse {
614
- userId?: string;
615
- roles: string[];
616
- permissions: Permission[];
617
- fetchedAt: Date;
618
- }
282
+ /** 权限 API 配置 Token */
283
+ declare const PERMISSION_API_CONFIG_TOKEN: unique symbol;
284
+ /** 缓存配置 Token */
285
+ declare const CACHE_CONFIG_TOKEN: unique symbol;
286
+ /** AuthZPaas 模块选项 Token */
287
+ declare const AUTHZPAAS_MODULE_OPTIONS: unique symbol;
619
288
  /**
620
- * 权限控制器
621
- * 提供权限查询接口,供前端客户端使用
289
+ * 元数据键
622
290
  */
623
- declare class PermissionController {
624
- private readonly permissionService;
625
- constructor(permissionService: PermissionService);
626
- /**
627
- * 获取当前用户的权限数据
628
- *
629
- * @param userId 当前用户ID(从请求上下文中获取)
630
- * @returns 用户权限数据
631
- *
632
- * @example
633
- * GET /api/permissions
634
- *
635
- * Response:
636
- * {
637
- * "userId": "user123",
638
- * "roles": ["admin", "user"],
639
- * "permissions": [
640
- * { "sub": "task", "actions": ["create", "read", "update", "delete"] }
641
- * ],
642
- * "fetchedAt": "2025-10-14T00:00:00.000Z"
643
- * }
644
- */
645
- getUserPermissions(userId: string, mockRoles: string[]): Promise<PermissionResponse>;
646
- /**
647
- * 开启角色模拟:将传入的 userId 写入 cookie,服务端优先使用该值请求权限
648
- */
649
- enableMock(res: Response, roles: string[]): Promise<{
650
- success: boolean;
651
- message: string;
652
- roles?: undefined;
653
- } | {
654
- success: boolean;
655
- roles: string[];
656
- message?: undefined;
657
- }>;
658
- /**
659
- * 关闭角色模拟:清除 cookie
660
- */
661
- disableMock(res: Response): Promise<{
662
- success: boolean;
663
- }>;
664
- getMockRoles(mockRoles: string[] | undefined, userId: string): Promise<{
665
- mocking: boolean;
666
- roles: string[];
667
- permissions: Permission[];
668
- fetchedAt: Date;
669
- userId: string;
670
- }>;
671
- }
291
+ /** 需要的角色元数据键 */
292
+ declare const ROLES_KEY = "authzpaas:roles";
293
+ /** 需要的权限元数据键 */
294
+ declare const PERMISSIONS_KEY = "authzpaas:permissions";
295
+ /** 需要的环境元数据键 */
296
+ declare const ENVIRONMENT_KEY = "authzpaas:environment";
297
+ /** 需要登录元数据键 */
298
+ declare const NEED_LOGIN_KEY = "authzpaas:needLogin";
299
+ /** 模块选项:登录页路径默认值 */
300
+ declare const DEFAULT_LOGIN_PATH = "/login";
301
+ /** 角色模拟的 Cookie 键名 */
302
+ declare const MOCK_ROLES_COOKIE_KEY = "mockRoles";
303
+ declare const ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
672
304
 
673
- export { ANONYMOUS_USER_ID, AUTHZPAAS_MODULE_OPTIONS, AbilityFactory, type Action, type AppAbility, AuthZPaasExceptionFilter, AuthZPaasGuard, AuthZPaasModule, type AuthZPaasModuleOptions, type AuthorizationContext, CACHE_CONFIG_TOKEN, type CacheConfig, CanEnv, CanPermission, CanRole, type CheckRoleRequirement, DEFAULT_LOGIN_PATH, type DeviceRequirement, ENABLE_MOCK_ROLE_KEY, ENVIRONMENT_KEY, type EnvironmentContext, type EnvironmentRequirement, MOCK_ROLES_COOKIE_KEY, MockRoles, NEED_LOGIN_KEY, type NetworkRequirement, PERMISSIONS_KEY, PERMISSION_API_CONFIG_TOKEN, type Permission, type PermissionApiConfig, PermissionController, type PermissionDeniedDetails, PermissionDeniedException, PermissionDeniedType, PermissionDto, type PermissionRequirement, PermissionResponse, PermissionService, ROLES_KEY, ROLE_SUBJECT, type RoleRequirement, RolesMiddleware, type Subject, type UserContext, UserId, type UserPermissionData, type UserRole };
305
+ export { ANONYMOUS_USER_ID, AUTHZPAAS_MODULE_OPTIONS, AbilityFactory, type Action, type AppAbility, AuthZPaasModule, type AuthZPaasModuleOptions, type AuthorizationContext, CACHE_CONFIG_TOKEN, CanRole, type CheckRoleRequirement, DEFAULT_LOGIN_PATH, ENABLE_MOCK_ROLE_KEY, ENVIRONMENT_KEY, type EnvironmentContext, MOCK_ROLES_COOKIE_KEY, NEED_LOGIN_KEY, PERMISSIONS_KEY, PERMISSION_API_CONFIG_TOKEN, type Permission, type PermissionApiConfig, type PermissionDeniedDetails, PermissionDeniedException, PermissionDeniedType, ROLES_KEY, ROLE_SUBJECT, type RoleRequirement, type Subject, type UserContext, type UserPermissionData, type UserRole, type UserRolesDTO };