@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.js CHANGED
@@ -2,144 +2,144 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/authzpaas.module.ts
5
- import { Module } from "@nestjs/common";
6
- import { APP_FILTER, APP_GUARD, Reflector as Reflector2 } from "@nestjs/core";
7
-
8
- // src/const.ts
9
- var ANONYMOUS_USER_ID = "anonymous_user_id";
10
- var PERMISSION_API_CONFIG_TOKEN = Symbol("PERMISSION_API_CONFIG");
11
- var CACHE_CONFIG_TOKEN = Symbol("CACHE_CONFIG");
12
- var AUTHZPAAS_MODULE_OPTIONS = Symbol("AUTHZPAAS_MODULE_OPTIONS");
13
- var ROLES_KEY = "authzpaas:roles";
14
- var PERMISSIONS_KEY = "authzpaas:permissions";
15
- var ENVIRONMENT_KEY = "authzpaas:environment";
16
- var NEED_LOGIN_KEY = "authzpaas:needLogin";
17
- var DEFAULT_LOGIN_PATH = "/login";
18
- var MOCK_ROLES_COOKIE_KEY = "mockRoles";
19
- var ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
5
+ import { Module as Module2 } from "@nestjs/common";
6
+ import { APP_GUARD as APP_GUARD2, Reflector as Reflector4 } from "@nestjs/core";
20
7
 
21
8
  // src/services/permission.service.ts
22
- import { Injectable as Injectable2, Inject, Logger, HttpStatus } from "@nestjs/common";
9
+ import { Injectable as Injectable3, Logger, HttpStatus, Inject } from "@nestjs/common";
23
10
 
24
- // src/utils/memory-cache.ts
25
- var MemoryCache = class {
11
+ // ../nestjs-authnpaas/dist/index.js
12
+ import { Module } from "@nestjs/common";
13
+ import { APP_GUARD, Reflector as Reflector2 } from "@nestjs/core";
14
+ import { Injectable } from "@nestjs/common";
15
+ import { Reflector } from "@nestjs/core";
16
+ import { SetMetadata } from "@nestjs/common";
17
+ import { SetMetadata as SetMetadata2 } from "@nestjs/common";
18
+ var __defProp2 = Object.defineProperty;
19
+ var __name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", {
20
+ value,
21
+ configurable: true
22
+ }), "__name");
23
+ var AUTHNPAAS_MODULE_OPTIONS = Symbol("AUTHNPAAS_MODULE_OPTIONS");
24
+ var NEED_LOGIN_KEY = "authnpaas:needLogin";
25
+ function _ts_decorate(decorators, target, key, desc) {
26
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
27
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
28
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
29
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
30
+ }
31
+ __name(_ts_decorate, "_ts_decorate");
32
+ __name2(_ts_decorate, "_ts_decorate");
33
+ function _ts_metadata(k, v) {
34
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
35
+ }
36
+ __name(_ts_metadata, "_ts_metadata");
37
+ __name2(_ts_metadata, "_ts_metadata");
38
+ var AuthNPaasGuard = class {
26
39
  static {
27
- __name(this, "MemoryCache");
40
+ __name(this, "AuthNPaasGuard");
28
41
  }
29
- cache;
30
- accessOrder;
31
- options;
32
- hits = 0;
33
- misses = 0;
34
- constructor(options) {
35
- this.cache = /* @__PURE__ */ new Map();
36
- this.accessOrder = [];
37
- this.options = options;
42
+ static {
43
+ __name2(this, "AuthNPaasGuard");
38
44
  }
39
- /**
40
- * 获取缓存值
41
- */
42
- get(key) {
43
- if (!this.options.enabled) {
44
- return void 0;
45
- }
46
- const item = this.cache.get(key);
47
- if (!item) {
48
- this.misses++;
49
- return void 0;
50
- }
51
- if (Date.now() > item.expireAt) {
52
- this.cache.delete(key);
53
- this.removeFromAccessOrder(key);
54
- this.misses++;
55
- return void 0;
56
- }
57
- this.updateAccessOrder(key);
58
- this.hits++;
59
- return item.value;
45
+ reflector;
46
+ constructor(reflector) {
47
+ this.reflector = reflector;
60
48
  }
61
- /**
62
- * 设置缓存值
63
- */
64
- set(key, value) {
65
- if (!this.options.enabled) {
66
- return;
67
- }
68
- if (this.cache.size >= this.options.max && !this.cache.has(key)) {
69
- this.evictLRU();
49
+ async canActivate(context) {
50
+ const http = context.switchToHttp();
51
+ const request = http.getRequest();
52
+ const response = http.getResponse();
53
+ const { userId, loginUrl } = request.userContext || {};
54
+ const needLoginMeta = this.reflector.getAllAndOverride(NEED_LOGIN_KEY, [
55
+ context.getHandler(),
56
+ context.getClass()
57
+ ]);
58
+ if (needLoginMeta && !userId && loginUrl) {
59
+ response.redirect(302, loginUrl);
60
+ return false;
70
61
  }
71
- const expireAt = Date.now() + this.options.ttl * 1e3;
72
- this.cache.set(key, {
73
- value,
74
- expireAt
75
- });
76
- this.updateAccessOrder(key);
62
+ return true;
77
63
  }
78
- /**
79
- * 删除缓存
80
- */
81
- delete(key) {
82
- this.cache.delete(key);
83
- this.removeFromAccessOrder(key);
64
+ };
65
+ AuthNPaasGuard = _ts_decorate([
66
+ Injectable(),
67
+ _ts_metadata("design:type", Function),
68
+ _ts_metadata("design:paramtypes", [
69
+ typeof Reflector === "undefined" ? Object : Reflector
70
+ ])
71
+ ], AuthNPaasGuard);
72
+ function _ts_decorate2(decorators, target, key, desc) {
73
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
74
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
75
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
76
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
77
+ }
78
+ __name(_ts_decorate2, "_ts_decorate2");
79
+ __name2(_ts_decorate2, "_ts_decorate");
80
+ var AuthNPaasModule = class _AuthNPaasModule {
81
+ static {
82
+ __name(this, "_AuthNPaasModule");
84
83
  }
85
- /**
86
- * 清空所有缓存
87
- */
88
- clear() {
89
- this.cache.clear();
90
- this.accessOrder = [];
91
- this.hits = 0;
92
- this.misses = 0;
84
+ static {
85
+ __name2(this, "AuthNPaasModule");
93
86
  }
94
- /**
95
- * 获取缓存统计信息
96
- */
97
- getStats() {
87
+ static forRoot(options) {
98
88
  return {
99
- size: this.cache.size,
100
- hits: this.hits,
101
- misses: this.misses,
102
- hitRate: this.hits / (this.hits + this.misses) || 0,
103
- enabled: this.options.enabled
89
+ module: _AuthNPaasModule,
90
+ global: true,
91
+ controllers: [],
92
+ providers: [
93
+ // 配置提供者
94
+ {
95
+ provide: AUTHNPAAS_MODULE_OPTIONS,
96
+ useValue: {
97
+ ...options || {}
98
+ }
99
+ },
100
+ // 核心服务
101
+ Reflector2,
102
+ // 服务提供者
103
+ AuthNPaasGuard,
104
+ // 守卫提供者
105
+ {
106
+ provide: APP_GUARD,
107
+ useClass: AuthNPaasGuard
108
+ }
109
+ ],
110
+ exports: []
104
111
  };
105
112
  }
106
- /**
107
- * 更新访问顺序
108
- */
109
- updateAccessOrder(key) {
110
- this.removeFromAccessOrder(key);
111
- this.accessOrder.push(key);
112
- }
113
- /**
114
- * 从访问顺序中移除
115
- */
116
- removeFromAccessOrder(key) {
117
- const index = this.accessOrder.indexOf(key);
118
- if (index > -1) {
119
- this.accessOrder.splice(index, 1);
120
- }
121
- }
122
- /**
123
- * 淘汰最少使用的项
124
- */
125
- evictLRU() {
126
- if (this.accessOrder.length > 0) {
127
- const oldestKey = this.accessOrder[0];
128
- this.delete(oldestKey);
129
- }
130
- }
131
113
  };
114
+ AuthNPaasModule = _ts_decorate2([
115
+ Module({})
116
+ ], AuthNPaasModule);
117
+ var IS_PUBLIC_KEY = "isPublic";
118
+ var Public = /* @__PURE__ */ __name2(() => SetMetadata(IS_PUBLIC_KEY, true), "Public");
119
+
120
+ // src/const.ts
121
+ var ANONYMOUS_USER_ID = "anonymous_user_id";
122
+ var PERMISSION_API_CONFIG_TOKEN = Symbol("PERMISSION_API_CONFIG");
123
+ var CACHE_CONFIG_TOKEN = Symbol("CACHE_CONFIG");
124
+ var AUTHZPAAS_MODULE_OPTIONS = Symbol("AUTHZPAAS_MODULE_OPTIONS");
125
+ var ROLES_KEY = "authzpaas:roles";
126
+ var PERMISSIONS_KEY = "authzpaas:permissions";
127
+ var ENVIRONMENT_KEY = "authzpaas:environment";
128
+ var NEED_LOGIN_KEY2 = "authzpaas:needLogin";
129
+ var DEFAULT_LOGIN_PATH = "/login";
130
+ var MOCK_ROLES_COOKIE_KEY = "mockRoles";
131
+ var ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
132
132
 
133
133
  // src/casl/ability.factory.ts
134
- import { Injectable } from "@nestjs/common";
134
+ import { Injectable as Injectable2 } from "@nestjs/common";
135
135
  import { AbilityBuilder, PureAbility } from "@casl/ability";
136
- function _ts_decorate(decorators, target, key, desc) {
136
+ function _ts_decorate3(decorators, target, key, desc) {
137
137
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
138
138
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
139
139
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
140
140
  return c > 3 && r && Object.defineProperty(target, key, r), r;
141
141
  }
142
- __name(_ts_decorate, "_ts_decorate");
142
+ __name(_ts_decorate3, "_ts_decorate");
143
143
  var ROLE_SUBJECT = "@role";
144
144
  var AbilityFactory = class {
145
145
  static {
@@ -150,20 +150,14 @@ var AbilityFactory = class {
150
150
  */
151
151
  createForUser(permissionData) {
152
152
  const { can, build } = new AbilityBuilder(PureAbility);
153
- for (const permission of permissionData.permissions) {
154
- const { sub, actions } = permission;
155
- for (const action of actions) {
156
- can(action, sub);
157
- }
158
- }
159
153
  for (const role of permissionData.roles) {
160
154
  can(role, ROLE_SUBJECT);
161
155
  }
162
156
  return build();
163
157
  }
164
158
  };
165
- AbilityFactory = _ts_decorate([
166
- Injectable()
159
+ AbilityFactory = _ts_decorate3([
160
+ Injectable2()
167
161
  ], AbilityFactory);
168
162
 
169
163
  // src/exceptions/permission-denied.exception.ts
@@ -172,7 +166,6 @@ var PermissionDeniedType = /* @__PURE__ */ (function(PermissionDeniedType2) {
172
166
  PermissionDeniedType2["UNAUTHENTICATED"] = "UNAUTHENTICATED";
173
167
  PermissionDeniedType2["ROLE_REQUIRED"] = "ROLE_REQUIRED";
174
168
  PermissionDeniedType2["PERMISSION_REQUIRED"] = "PERMISSION_REQUIRED";
175
- PermissionDeniedType2["ENVIRONMENT_REQUIRED"] = "ENVIRONMENT_REQUIRED";
176
169
  PermissionDeniedType2["PERMISSION_CONFIG_QUERY_FAILED"] = "PERMISSION_CONFIG_QUERY_FAILED";
177
170
  return PermissionDeniedType2;
178
171
  })({});
@@ -250,30 +243,20 @@ var PermissionDeniedException = class _PermissionDeniedException extends HttpExc
250
243
  }
251
244
  });
252
245
  }
253
- /**
254
- * 创建环境不满足异常
255
- */
256
- static environmentRequired(requirement, message) {
257
- return new _PermissionDeniedException({
258
- type: "ENVIRONMENT_REQUIRED",
259
- message: message || "\u4E0D\u6EE1\u8DB3\u73AF\u5883\u8981\u6C42",
260
- environmentRequirement: requirement
261
- });
262
- }
263
246
  };
264
247
 
265
248
  // src/services/permission.service.ts
266
- function _ts_decorate2(decorators, target, key, desc) {
249
+ function _ts_decorate4(decorators, target, key, desc) {
267
250
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
268
251
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
269
252
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
270
253
  return c > 3 && r && Object.defineProperty(target, key, r), r;
271
254
  }
272
- __name(_ts_decorate2, "_ts_decorate");
273
- function _ts_metadata(k, v) {
255
+ __name(_ts_decorate4, "_ts_decorate");
256
+ function _ts_metadata2(k, v) {
274
257
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
275
258
  }
276
- __name(_ts_metadata, "_ts_metadata");
259
+ __name(_ts_metadata2, "_ts_metadata");
277
260
  function _ts_param(paramIndex, decorator) {
278
261
  return function(target, key) {
279
262
  decorator(target, key, paramIndex);
@@ -287,90 +270,49 @@ var PermissionService = class _PermissionService {
287
270
  apiConfig;
288
271
  abilityFactory;
289
272
  logger = new Logger(_PermissionService.name);
290
- // 统一的缓存,同时缓存权限数据和 Ability 实例
291
- cache;
292
- // 缓存正在进行中的 Promise,避免重复请求
293
- pendingRequests = /* @__PURE__ */ new Map();
294
- constructor(apiConfig, cacheConfig, abilityFactory) {
273
+ constructor(apiConfig, abilityFactory) {
295
274
  this.apiConfig = apiConfig;
296
275
  this.abilityFactory = abilityFactory;
297
- this.cache = new MemoryCache({
298
- ttl: cacheConfig.ttl || 300,
299
- max: cacheConfig.max || 1e3,
300
- enabled: cacheConfig.enabled !== false
301
- });
302
- this.logger.log(`PermissionService initialized with API: ${apiConfig?.baseUrl}`);
303
- }
304
- /**
305
- * 构建权限/Ability 缓存 key
306
- * - 若存在模拟角色:按角色集合排序拼接 + 用户维度
307
- * - 否则按 userId/匿名用户
308
- */
309
- buildCacheKey(userId, mockRoles) {
310
- if (mockRoles && mockRoles.length > 0) {
311
- const sortedRoles = [
312
- ...mockRoles
313
- ].sort();
314
- return `@roles:${sortedRoles.join("|")}#u:${userId || ANONYMOUS_USER_ID}`;
315
- }
316
- return userId || ANONYMOUS_USER_ID;
317
276
  }
318
277
  /**
319
- * 获取用户权限数据(带缓存)
278
+ * 获取用户权限数据
320
279
  */
321
- async getUserPermissions(userId, mockRoles) {
322
- if (!this.apiConfig?.endpoint) {
323
- this.logger.warn("Permission API endpoint is not configured, returning null");
324
- return null;
325
- }
326
- const key = this.buildCacheKey(userId, mockRoles);
327
- const cached = this.cache.get(key);
328
- if (cached) {
329
- this.logger.debug(`Cache hit for user ${key}`);
330
- return cached.permissionData;
331
- }
332
- const pendingRequest = this.pendingRequests.get(key);
333
- if (pendingRequest) {
334
- this.logger.debug(`Reusing pending request for user ${key}`);
335
- return pendingRequest;
336
- }
337
- this.logger.debug(`Cache miss for key ${key}, fetching from API`);
280
+ async getUserPermissions(requestDto) {
338
281
  const requestPromise = (async () => {
282
+ const userId = requestDto.userId || ANONYMOUS_USER_ID;
339
283
  try {
340
- const permissionData = mockRoles && mockRoles.length > 0 ? await this.getPermissionsByMockRoles(userId, mockRoles) : await this.fetchFromApi(userId);
284
+ const permissionData = await this.fetchFromApi(requestDto);
341
285
  const dataWithTimestamp = {
342
286
  ...permissionData,
343
287
  fetchedAt: /* @__PURE__ */ new Date()
344
288
  };
345
- const ability = this.abilityFactory.createForUser(dataWithTimestamp);
346
- this.cache.set(key, {
347
- permissionData: dataWithTimestamp,
348
- ability
349
- });
350
289
  return dataWithTimestamp;
351
290
  } catch (error) {
352
- this.logger.error(`Failed to fetch permissions for key ${key}:`, error);
291
+ this.logger.error(`Failed to fetch permissions for user ${userId}:`, error);
353
292
  throw error;
354
- } finally {
355
- this.pendingRequests.delete(key);
356
293
  }
357
294
  })();
358
- this.pendingRequests.set(key, requestPromise);
359
295
  return requestPromise;
360
296
  }
361
297
  /**
362
298
  * 从 API 获取权限数据
363
299
  * 内置实现,用户无需配置
364
300
  */
365
- async fetchFromApi(userId) {
366
- const { baseUrl, apiToken, endpoint, headers = {}, timeout = 5e3 } = this.apiConfig || {};
367
- const url = `${baseUrl}${endpoint}${userId ? `?userId=${userId}` : ""}`;
301
+ async fetchFromApi(requestDto) {
302
+ const { timeout = 5e3 } = this.apiConfig || {};
303
+ const { baseUrl, userId, appId, cookies, csrfToken } = requestDto;
304
+ const url = `${baseUrl}/api/v1/permission/apps/${appId}/roles`;
368
305
  const requestHeaders = {
369
- "Content-Type": "application/json",
370
- ...headers
306
+ "Content-Type": "application/json"
371
307
  };
372
- if (apiToken) {
373
- requestHeaders["Authorization"] = `Bearer ${apiToken}`;
308
+ if (cookies) {
309
+ const cookieString = Object.entries(cookies).map(([key, value]) => `${key}=${value}`).join("; ");
310
+ if (cookieString) {
311
+ requestHeaders.Cookie = cookieString;
312
+ }
313
+ }
314
+ if (csrfToken) {
315
+ requestHeaders["X-Suda-Csrf-Token"] = csrfToken;
374
316
  }
375
317
  const controller = new AbortController();
376
318
  const timeoutId = setTimeout(() => controller.abort(), timeout);
@@ -390,11 +332,11 @@ var PermissionService = class _PermissionService {
390
332
  }, HttpStatus.INTERNAL_SERVER_ERROR);
391
333
  }
392
334
  const data = await response.json();
393
- const roles = (data.roles || []).map((role) => typeof role === "string" ? role : role.name);
394
335
  return {
395
336
  userId,
396
- roles,
397
- permissions: data.permissions || [],
337
+ roles: data.role_list || [],
338
+ // TODO: 基于权限点位设置能力
339
+ // permissions: data.permissions || [],
398
340
  fetchedAt: /* @__PURE__ */ new Date()
399
341
  };
400
342
  } catch (error) {
@@ -410,80 +352,28 @@ var PermissionService = class _PermissionService {
410
352
  }, HttpStatus.INTERNAL_SERVER_ERROR);
411
353
  }
412
354
  }
413
- /**
414
- * 基于模拟角色获取权限数据(不使用缓存)
415
- * 该方法用于前端/守卫在检测到 mockRoles 时直接按角色获取权限
416
- */
417
- async getPermissionsByMockRoles(userId, mockRoles) {
418
- const { baseUrl, timeout = 5e3 } = this.apiConfig || {};
419
- const rolesParam = encodeURIComponent(mockRoles.join(","));
420
- const userParam = userId ? `&userId=${encodeURIComponent(userId)}` : "";
421
- const url = `${baseUrl}/mock-api/permissions-by-roles?roles=${rolesParam}${userParam}`;
422
- const controller = new AbortController();
423
- const timeoutId = setTimeout(() => controller.abort(), timeout);
424
- try {
425
- const response = await fetch(url, {
426
- method: "GET",
427
- signal: controller.signal
428
- });
429
- clearTimeout(timeoutId);
430
- if (!response.ok) {
431
- throw new Error(`Permission API (mock by roles) returned ${response.status}: ${response.statusText}`);
432
- }
433
- const data = await response.json();
434
- return {
435
- userId,
436
- roles: data.roles || [],
437
- permissions: data.permissions || [],
438
- fetchedAt: /* @__PURE__ */ new Date()
439
- };
440
- } catch (error) {
441
- clearTimeout(timeoutId);
442
- throw new PermissionDeniedException({
443
- cause: error,
444
- type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
445
- message: error.message
446
- }, HttpStatus.INTERNAL_SERVER_ERROR);
447
- }
448
- }
449
- /**
450
- * 获取用户的 Ability 实例(带缓存)
451
- * @param userId 用户ID
452
- * @returns CASL Ability 实例
453
- */
454
- async getUserAbility(userId, mockRoles) {
455
- const key = this.buildCacheKey(userId, mockRoles);
456
- const cached = this.cache.get(key);
457
- if (cached) {
458
- return cached.ability;
459
- }
460
- await this.getUserPermissions(userId, mockRoles);
461
- const newCached = this.cache.get(key);
462
- return newCached.ability;
463
- }
464
- /**
465
- * 清除用户权限缓存
466
- */
467
- clearUserCache(userId) {
468
- const key = userId || ANONYMOUS_USER_ID;
469
- this.cache.delete(key);
470
- this.pendingRequests.delete(key);
471
- this.logger.debug(`Cache cleared for user ${key}`);
472
- }
473
- /**
474
- * 清除所有缓存
475
- */
476
- clearAllCache() {
477
- this.cache.clear();
478
- this.pendingRequests.clear();
479
- this.logger.log("All permission cache cleared");
480
- }
481
- /**
482
- * 获取缓存统计信息
483
- */
484
- getCacheStats() {
485
- return this.cache.getStats();
486
- }
355
+ // /**
356
+ // * 获取用户的 Ability 实例(带缓存)
357
+ // * @param userId 用户ID
358
+ // * @returns CASL Ability 实例
359
+ // */
360
+ // private async getUserAbility(
361
+ // userId?: string,
362
+ // mockRoles?: string[]
363
+ // ): Promise<AppAbility> {
364
+ // // 计算缓存 key
365
+ // const key = this.buildCacheKey(userId, mockRoles);
366
+ // // 尝试从缓存获取
367
+ // const cached = this.cache.get(key);
368
+ // if (cached) {
369
+ // return cached.ability;
370
+ // }
371
+ // // 缓存未命中,调用 getUserPermissions 会创建并缓存
372
+ // await this.getUserPermissions(userId, mockRoles);
373
+ // // 再次从缓存获取(此时一定存在)
374
+ // const newCached = this.cache.get(key);
375
+ // return newCached!.ability;
376
+ // }
487
377
  /**
488
378
  * 检查角色要求
489
379
  * 使用 CASL Ability 统一鉴权方式
@@ -492,8 +382,15 @@ var PermissionService = class _PermissionService {
492
382
  * @returns 用户权限数据
493
383
  * @throws PermissionDeniedException 当角色不满足时
494
384
  */
495
- async checkRoles(requirement, userId, mockRoles) {
496
- const permissionData = await this.getUserPermissions(userId, mockRoles);
385
+ async checkRoles(requirement, userContext) {
386
+ const userId = userContext?.userId || ANONYMOUS_USER_ID;
387
+ const permissionData = await this.getUserPermissions({
388
+ baseUrl: userContext?.baseUrl || "",
389
+ userId,
390
+ appId: userContext?.appId || "",
391
+ cookies: userContext?.cookies || {},
392
+ csrfToken: userContext?.csrfToken || ""
393
+ });
497
394
  if (!permissionData) {
498
395
  throw new PermissionDeniedException({
499
396
  cause: new Error("Permission data fetch api is not configured"),
@@ -501,7 +398,7 @@ var PermissionService = class _PermissionService {
501
398
  message: "Permission data fetch api is not configured"
502
399
  }, HttpStatus.BAD_REQUEST);
503
400
  }
504
- const ability = await this.getUserAbility(userId, mockRoles);
401
+ const ability = this.abilityFactory.createForUser(permissionData);
505
402
  const { roles, and } = requirement;
506
403
  const checkResults = roles.map((role) => ability.can(role, ROLE_SUBJECT));
507
404
  const hasRole = and ? checkResults.every((result) => result) : checkResults.some((result) => result);
@@ -512,371 +409,70 @@ var PermissionService = class _PermissionService {
512
409
  }
513
410
  return permissionData;
514
411
  }
515
- /**
516
- * 检查权限要求
517
- * @param requirements 权限要求列表
518
- * @param userId 用户ID
519
- * @returns 用户权限数据
520
- * @throws PermissionDeniedException 当权限不满足时
521
- */
522
- async checkPermissions(params, userId, mockRoles) {
523
- const permissionData = await this.getUserPermissions(userId, mockRoles);
524
- if (!permissionData) {
525
- throw new PermissionDeniedException({
526
- cause: new Error("Permission data fetch api is not configured"),
527
- type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
528
- message: "Permission data fetch api is not configured"
529
- }, HttpStatus.BAD_REQUEST);
530
- }
531
- const { requirements, or } = params;
532
- if (!requirements || requirements.length === 0) {
533
- return permissionData;
534
- }
535
- const ability = await this.getUserAbility(userId, mockRoles);
536
- const failedRequirements = [];
537
- for (const requirement of requirements) {
538
- const { actions, subject, or: or2 = false } = requirement;
539
- const checkResults = actions.map((action) => ability.can(action, subject));
540
- const hasPermission = or2 ? checkResults.some((result) => result) : checkResults.every((result) => result);
541
- if (!hasPermission) {
542
- failedRequirements.push({
543
- actions,
544
- subject: String(subject),
545
- or: or2
546
- });
547
- }
548
- }
549
- if (failedRequirements.length > 0) {
550
- if (or && failedRequirements.length === requirements.length) {
551
- throw PermissionDeniedException.permissionRequired(failedRequirements.map(({ actions, subject }) => ({
552
- actions,
553
- subject: String(subject)
554
- })), true);
555
- } else if (!or) {
556
- throw PermissionDeniedException.permissionRequired(failedRequirements.map(({ actions, subject }) => ({
557
- actions,
558
- subject: String(subject)
559
- })), false);
560
- }
561
- }
562
- return permissionData;
563
- }
564
- async getAbility(userId) {
565
- return this.getUserAbility(userId);
566
- }
567
412
  };
568
- PermissionService = _ts_decorate2([
569
- Injectable2(),
413
+ PermissionService = _ts_decorate4([
414
+ Injectable3(),
415
+ Public(),
570
416
  _ts_param(0, Inject(PERMISSION_API_CONFIG_TOKEN)),
571
- _ts_param(1, Inject(CACHE_CONFIG_TOKEN)),
572
- _ts_metadata("design:type", Function),
573
- _ts_metadata("design:paramtypes", [
417
+ _ts_metadata2("design:type", Function),
418
+ _ts_metadata2("design:paramtypes", [
574
419
  typeof PermissionApiConfig === "undefined" ? Object : PermissionApiConfig,
575
- typeof CacheConfig === "undefined" ? Object : CacheConfig,
576
420
  typeof AbilityFactory === "undefined" ? Object : AbilityFactory
577
421
  ])
578
422
  ], PermissionService);
579
423
 
580
424
  // src/guards/authzpaas.guard.ts
581
- import { Injectable as Injectable3, Inject as Inject2 } from "@nestjs/common";
582
- import { Reflector } from "@nestjs/core";
583
-
584
- // src/utils/index.ts
585
- function getMockRolesFromCookie(request) {
586
- const mockRoles = request.cookies?.[MOCK_ROLES_COOKIE_KEY];
587
- return mockRoles ? mockRoles.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
588
- }
589
- __name(getMockRolesFromCookie, "getMockRolesFromCookie");
590
-
591
- // src/guards/authzpaas.guard.ts
592
- function _ts_decorate3(decorators, target, key, desc) {
425
+ import { Injectable as Injectable4 } from "@nestjs/common";
426
+ import { Reflector as Reflector3 } from "@nestjs/core";
427
+ function _ts_decorate5(decorators, target, key, desc) {
593
428
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
594
429
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
595
430
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
596
431
  return c > 3 && r && Object.defineProperty(target, key, r), r;
597
432
  }
598
- __name(_ts_decorate3, "_ts_decorate");
599
- function _ts_metadata2(k, v) {
433
+ __name(_ts_decorate5, "_ts_decorate");
434
+ function _ts_metadata3(k, v) {
600
435
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
601
436
  }
602
- __name(_ts_metadata2, "_ts_metadata");
603
- function _ts_param2(paramIndex, decorator) {
604
- return function(target, key) {
605
- decorator(target, key, paramIndex);
606
- };
607
- }
608
- __name(_ts_param2, "_ts_param");
437
+ __name(_ts_metadata3, "_ts_metadata");
609
438
  var AuthZPaasGuard = class {
610
439
  static {
611
440
  __name(this, "AuthZPaasGuard");
612
441
  }
613
442
  reflector;
614
443
  permissionService;
615
- moduleOptions;
616
- constructor(reflector, permissionService, moduleOptions) {
444
+ constructor(reflector, permissionService) {
617
445
  this.reflector = reflector;
618
446
  this.permissionService = permissionService;
619
- this.moduleOptions = moduleOptions;
620
447
  }
621
448
  async canActivate(context) {
622
449
  const http = context.switchToHttp();
623
450
  const request = http.getRequest();
624
- request[ENABLE_MOCK_ROLE_KEY] = this.moduleOptions?.enableMockRole;
625
- const userId = this.extractUserId(request);
626
- const mockRoles = this.moduleOptions?.enableMockRole ? getMockRolesFromCookie(request) : void 0;
451
+ const userContext = request.userContext;
627
452
  const checkRoleRequirement = this.reflector.getAllAndOverride(ROLES_KEY, [
628
453
  context.getHandler(),
629
454
  context.getClass()
630
455
  ]);
631
456
  if (checkRoleRequirement) {
632
- await this.checkRoleRequirement(checkRoleRequirement, userId, mockRoles);
633
- }
634
- const checkPermissionParams = this.reflector.getAllAndOverride(PERMISSIONS_KEY, [
635
- context.getHandler(),
636
- context.getClass()
637
- ]);
638
- if (checkPermissionParams) {
639
- await this.checkPermissionRequirement(checkPermissionParams, userId, mockRoles);
640
- }
641
- const envRequirement = this.reflector.getAllAndOverride(ENVIRONMENT_KEY, [
642
- context.getHandler(),
643
- context.getClass()
644
- ]);
645
- if (envRequirement) {
646
- const envContext = this.extractEnvironmentContext(request);
647
- await this.checkEnvironmentRequirement(envRequirement, envContext, request);
457
+ await this.checkRoleRequirement(checkRoleRequirement, userContext);
648
458
  }
649
459
  return true;
650
460
  }
651
461
  /**
652
- * 从请求中提取用户ID
653
- * 子类可以重写此方法以适应不同的认证策略
654
- */
655
- extractUserId(request) {
656
- const mockUserId = request.cookies?.mockUserId;
657
- if (mockUserId) return mockUserId;
658
- return request.userContext?.userId;
659
- }
660
- /**
661
- * 从请求中提取环境上下文
662
- */
663
- extractEnvironmentContext(request) {
664
- const regionHeader = request.headers["x-region"];
665
- const osHeader = request.headers["x-os"];
666
- const uaHeader = request.headers["user-agent"];
667
- const region = Array.isArray(regionHeader) ? regionHeader[0] : regionHeader;
668
- const os = Array.isArray(osHeader) ? osHeader[0] : osHeader;
669
- const userAgent = Array.isArray(uaHeader) ? uaHeader[0] : uaHeader;
670
- return {
671
- network: {
672
- ip: request.ip || request.connection?.remoteAddress,
673
- region
674
- },
675
- device: {
676
- type: this.detectDeviceType(userAgent),
677
- os,
678
- browser: userAgent
679
- },
680
- custom: {
681
- headers: request.headers,
682
- query: request.query
683
- }
684
- };
685
- }
686
- /**
687
- * 检测设备类型
688
- */
689
- detectDeviceType(userAgent) {
690
- if (!userAgent) return "desktop";
691
- const ua = userAgent.toLowerCase();
692
- if (/(tablet|ipad|playbook|silk)|(android(?!.*mobile))/i.test(ua)) {
693
- return "tablet";
694
- }
695
- if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) {
696
- return "mobile";
697
- }
698
- return "desktop";
699
- }
700
- /**
701
462
  * 检查角色要求
702
463
  */
703
- async checkRoleRequirement(requirement, userId, mockRoles) {
704
- return this.permissionService.checkRoles(requirement, userId, mockRoles);
705
- }
706
- /**
707
- * 检查权限要求
708
- */
709
- async checkPermissionRequirement(params, userId, mockRoles) {
710
- return this.permissionService.checkPermissions(params, userId, mockRoles);
711
- }
712
- /**
713
- * 检查环境要求
714
- */
715
- async checkEnvironmentRequirement(requirement, envContext, request) {
716
- if (requirement.network) {
717
- await this.checkNetworkRequirement(requirement.network, envContext);
718
- }
719
- if (requirement.device) {
720
- await this.checkDeviceRequirement(requirement.device, envContext);
721
- }
722
- if (requirement.custom) {
723
- const result = await requirement.custom(request);
724
- if (!result) {
725
- throw PermissionDeniedException.environmentRequired("custom", "\u4E0D\u6EE1\u8DB3\u81EA\u5B9A\u4E49\u73AF\u5883\u8981\u6C42");
726
- }
727
- }
728
- }
729
- /**
730
- * 检查网络要求
731
- */
732
- async checkNetworkRequirement(requirement, envContext) {
733
- const ip = envContext.network?.ip;
734
- if (requirement.allowedIPs && ip) {
735
- const isAllowed = this.checkIPMatch(ip, requirement.allowedIPs);
736
- if (!isAllowed) {
737
- throw PermissionDeniedException.environmentRequired("network.allowedIPs", `IP \u5730\u5740\u4E0D\u5728\u5141\u8BB8\u5217\u8868\u4E2D: ${ip}`);
738
- }
739
- }
740
- if (requirement.blockedIPs && ip) {
741
- const isBlocked = this.checkIPMatch(ip, requirement.blockedIPs);
742
- if (isBlocked) {
743
- throw PermissionDeniedException.environmentRequired("network.blockedIPs", `IP \u5730\u5740\u88AB\u7981\u6B62\u8BBF\u95EE: ${ip}`);
744
- }
745
- }
746
- if (requirement.allowedRegions && envContext.network?.region) {
747
- const isAllowed = requirement.allowedRegions.includes(envContext.network.region);
748
- if (!isAllowed) {
749
- throw PermissionDeniedException.environmentRequired("network.allowedRegions", `\u5730\u533A\u4E0D\u5728\u5141\u8BB8\u5217\u8868\u4E2D: ${envContext.network.region}`);
750
- }
751
- }
752
- }
753
- /**
754
- * 检查设备要求
755
- */
756
- async checkDeviceRequirement(requirement, envContext) {
757
- if (requirement.types && envContext.device?.type) {
758
- const isAllowed = requirement.types.includes(envContext.device.type);
759
- if (!isAllowed) {
760
- throw PermissionDeniedException.environmentRequired("device.types", `\u4E0D\u5141\u8BB8\u7684\u8BBE\u5907\u7C7B\u578B: ${envContext.device.type}`);
761
- }
762
- }
763
- }
764
- /**
765
- * 检查 IP 是否匹配
766
- * 简化版本,仅支持精确匹配
767
- * 生产环境建议使用 ipaddr.js 等库
768
- */
769
- checkIPMatch(ip, patterns) {
770
- return patterns.some((pattern) => {
771
- if (pattern === ip) return true;
772
- return false;
773
- });
464
+ async checkRoleRequirement(requirement, userContext) {
465
+ return this.permissionService.checkRoles(requirement, userContext);
774
466
  }
775
467
  };
776
- AuthZPaasGuard = _ts_decorate3([
777
- Injectable3(),
778
- _ts_param2(2, Inject2(AUTHZPAAS_MODULE_OPTIONS)),
779
- _ts_metadata2("design:type", Function),
780
- _ts_metadata2("design:paramtypes", [
781
- typeof Reflector === "undefined" ? Object : Reflector,
782
- typeof PermissionService === "undefined" ? Object : PermissionService,
783
- typeof AuthZPaasModuleOptions === "undefined" ? Object : AuthZPaasModuleOptions
784
- ])
785
- ], AuthZPaasGuard);
786
-
787
- // src/middlewares/roles.middleware.ts
788
- import { Injectable as Injectable4, Logger as Logger2 } from "@nestjs/common";
789
- function _ts_decorate4(decorators, target, key, desc) {
790
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
791
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
792
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
793
- return c > 3 && r && Object.defineProperty(target, key, r), r;
794
- }
795
- __name(_ts_decorate4, "_ts_decorate");
796
- function _ts_metadata3(k, v) {
797
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
798
- }
799
- __name(_ts_metadata3, "_ts_metadata");
800
- var RolesMiddleware = class _RolesMiddleware {
801
- static {
802
- __name(this, "RolesMiddleware");
803
- }
804
- permissionService;
805
- logger = new Logger2(_RolesMiddleware.name);
806
- constructor(permissionService) {
807
- this.permissionService = permissionService;
808
- }
809
- async use(req, _res, next) {
810
- try {
811
- const userId = req.userContext?.userId;
812
- const mockRoles = req[ENABLE_MOCK_ROLE_KEY] ? getMockRolesFromCookie(req) : void 0;
813
- this.logger.debug(`Fetching roles for user: ${userId}`);
814
- const permissionData = await this.permissionService.getUserPermissions(userId, mockRoles);
815
- let roles;
816
- if (permissionData) {
817
- roles = permissionData.roles;
818
- }
819
- req.userContext.userRoles = roles;
820
- req.userContext.userId = userId;
821
- this.logger.debug(`User ${userId} roles loaded: [${roles?.join(", ")}]`);
822
- next();
823
- } catch (error) {
824
- this.logger.warn(`Failed to fetch roles for request: ${error instanceof Error ? error.message : "Unknown error"}`);
825
- next();
826
- }
827
- }
828
- };
829
- RolesMiddleware = _ts_decorate4([
468
+ AuthZPaasGuard = _ts_decorate5([
830
469
  Injectable4(),
831
470
  _ts_metadata3("design:type", Function),
832
471
  _ts_metadata3("design:paramtypes", [
472
+ typeof Reflector3 === "undefined" ? Object : Reflector3,
833
473
  typeof PermissionService === "undefined" ? Object : PermissionService
834
474
  ])
835
- ], RolesMiddleware);
836
-
837
- // src/filters/authzpaas-exception.filter.ts
838
- import { Catch } from "@nestjs/common";
839
- function _ts_decorate5(decorators, target, key, desc) {
840
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
841
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
842
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
843
- return c > 3 && r && Object.defineProperty(target, key, r), r;
844
- }
845
- __name(_ts_decorate5, "_ts_decorate");
846
- var AuthZPaasExceptionFilter = class {
847
- static {
848
- __name(this, "AuthZPaasExceptionFilter");
849
- }
850
- catch(exception, host) {
851
- const ctx = host.switchToHttp();
852
- const response = ctx.getResponse();
853
- const status = exception.getStatus();
854
- const exceptionResponse = exception.getResponse();
855
- const errorResponse = {
856
- statusCode: status,
857
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
858
- cause: exception.cause,
859
- type: exception.type,
860
- message: typeof exceptionResponse === "string" ? exceptionResponse : exceptionResponse.message || "\u6743\u9650\u4E0D\u8DB3"
861
- };
862
- if (exception.details.requiredRoles) {
863
- errorResponse.requiredRoles = exception.details.requiredRoles;
864
- }
865
- if (exception.details.requiredPermissions) {
866
- errorResponse.requiredPermissions = exception.details.requiredPermissions;
867
- }
868
- if (exception.details.environmentRequirement) {
869
- errorResponse.environmentRequirement = exception.details.environmentRequirement;
870
- }
871
- if (exception.details.metadata) {
872
- errorResponse.metadata = exception.details.metadata;
873
- }
874
- response.status(status).json(errorResponse);
875
- }
876
- };
877
- AuthZPaasExceptionFilter = _ts_decorate5([
878
- Catch(PermissionDeniedException)
879
- ], AuthZPaasExceptionFilter);
475
+ ], AuthZPaasGuard);
880
476
 
881
477
  // src/authzpaas.module.ts
882
478
  function _ts_decorate6(decorators, target, key, desc) {
@@ -891,53 +487,38 @@ var AuthZPaasModule = class _AuthZPaasModule {
891
487
  __name(this, "AuthZPaasModule");
892
488
  }
893
489
  static forRoot(options) {
894
- const { permissionApi, cache = {
895
- ttl: 300,
896
- max: 1e3,
897
- enabled: true
898
- }, isGlobal = true } = options;
490
+ const { permissionApi } = options;
899
491
  return {
900
492
  module: _AuthZPaasModule,
901
- global: isGlobal,
493
+ global: true,
902
494
  controllers: [],
903
495
  providers: [
904
496
  // 配置提供者
905
497
  {
906
498
  provide: AUTHZPAAS_MODULE_OPTIONS,
907
499
  useValue: {
908
- ...options,
909
- loginPath: options.loginPath || DEFAULT_LOGIN_PATH
500
+ ...options
910
501
  }
911
502
  },
912
503
  {
913
504
  provide: PERMISSION_API_CONFIG_TOKEN,
914
505
  useValue: permissionApi
915
506
  },
916
- {
917
- provide: CACHE_CONFIG_TOKEN,
918
- useValue: cache
919
- },
920
507
  // 核心服务
921
- Reflector2,
508
+ Reflector4,
922
509
  // 服务提供者
923
510
  PermissionService,
924
511
  AbilityFactory,
925
512
  AuthZPaasGuard,
926
- RolesMiddleware,
927
513
  // 守卫提供者
928
514
  {
929
- provide: APP_GUARD,
515
+ provide: APP_GUARD2,
930
516
  useClass: AuthZPaasGuard
931
- },
932
- {
933
- provide: APP_FILTER,
934
- useClass: AuthZPaasExceptionFilter
935
517
  }
936
518
  ],
937
519
  exports: [
938
520
  PermissionService,
939
- AbilityFactory,
940
- RolesMiddleware
521
+ AbilityFactory
941
522
  ]
942
523
  };
943
524
  }
@@ -972,10 +553,10 @@ var AuthZPaasModule = class _AuthZPaasModule {
972
553
  * ```
973
554
  */
974
555
  static forRootAsync(options) {
975
- const { imports = [], inject = [], useFactory, isGlobal = true } = options;
556
+ const { imports = [], inject = [], useFactory } = options;
976
557
  return {
977
558
  module: _AuthZPaasModule,
978
- global: isGlobal,
559
+ global: true,
979
560
  imports,
980
561
  controllers: [],
981
562
  providers: [
@@ -995,51 +576,31 @@ var AuthZPaasModule = class _AuthZPaasModule {
995
576
  AUTHZPAAS_MODULE_OPTIONS
996
577
  ]
997
578
  },
998
- // 缓存配置提供者
999
- {
1000
- provide: CACHE_CONFIG_TOKEN,
1001
- useFactory: /* @__PURE__ */ __name((moduleOptions) => {
1002
- return moduleOptions.cache || {
1003
- ttl: 300,
1004
- max: 1e3,
1005
- enabled: true
1006
- };
1007
- }, "useFactory"),
1008
- inject: [
1009
- AUTHZPAAS_MODULE_OPTIONS
1010
- ]
1011
- },
1012
579
  // 核心服务
1013
- Reflector2,
580
+ Reflector4,
1014
581
  // 服务提供者
1015
582
  PermissionService,
1016
583
  AbilityFactory,
1017
584
  AuthZPaasGuard,
1018
- RolesMiddleware,
1019
585
  // 守卫提供者
1020
586
  {
1021
- provide: APP_GUARD,
587
+ provide: APP_GUARD2,
1022
588
  useClass: AuthZPaasGuard
1023
- },
1024
- {
1025
- provide: APP_FILTER,
1026
- useClass: AuthZPaasExceptionFilter
1027
589
  }
1028
590
  ],
1029
591
  exports: [
1030
592
  PermissionService,
1031
- AbilityFactory,
1032
- RolesMiddleware
593
+ AbilityFactory
1033
594
  ]
1034
595
  };
1035
596
  }
1036
597
  };
1037
598
  AuthZPaasModule = _ts_decorate6([
1038
- Module({})
599
+ Module2({})
1039
600
  ], AuthZPaasModule);
1040
601
 
1041
602
  // src/decorators/can-role.decorator.ts
1042
- import { SetMetadata } from "@nestjs/common";
603
+ import { SetMetadata as SetMetadata3 } from "@nestjs/common";
1043
604
  var CanRole = /* @__PURE__ */ __name((role, and = false) => {
1044
605
  let requirement;
1045
606
  if (!Array.isArray(role) && typeof role === "string") {
@@ -1057,364 +618,25 @@ var CanRole = /* @__PURE__ */ __name((role, and = false) => {
1057
618
  } else {
1058
619
  throw new Error("Invalid CanRole parameter: " + JSON.stringify(role));
1059
620
  }
1060
- return SetMetadata(ROLES_KEY, requirement);
621
+ return SetMetadata3(ROLES_KEY, requirement);
1061
622
  }, "CanRole");
1062
-
1063
- // src/decorators/can-permission.decorator.ts
1064
- import { SetMetadata as SetMetadata2 } from "@nestjs/common";
1065
- var CanPermission = /* @__PURE__ */ __name((permission, or) => {
1066
- let requirements;
1067
- if (Array.isArray(permission)) {
1068
- requirements = permission;
1069
- } else if (typeof permission === "object" && "subject" in permission) {
1070
- requirements = [
1071
- permission
1072
- ];
1073
- } else {
1074
- throw new Error("Invalid CanPermission parameter: " + JSON.stringify(permission));
1075
- }
1076
- return SetMetadata2(PERMISSIONS_KEY, {
1077
- requirements,
1078
- or: or ?? false
1079
- });
1080
- }, "CanPermission");
1081
-
1082
- // src/decorators/can-env.decorator.ts
1083
- import { SetMetadata as SetMetadata3 } from "@nestjs/common";
1084
- var CanEnv = /* @__PURE__ */ __name((requirement) => {
1085
- return SetMetadata3(ENVIRONMENT_KEY, requirement);
1086
- }, "CanEnv");
1087
-
1088
- // src/decorators/user-id.decorator.ts
1089
- import { createParamDecorator } from "@nestjs/common";
1090
- var UserId = createParamDecorator((_data, ctx) => {
1091
- const request = ctx.switchToHttp().getRequest();
1092
- return request.userContext?.userId;
1093
- });
1094
-
1095
- // src/decorators/mock-roles.decorator.ts
1096
- import { createParamDecorator as createParamDecorator2 } from "@nestjs/common";
1097
- var MockRoles = createParamDecorator2((_data, ctx) => {
1098
- const request = ctx.switchToHttp().getRequest();
1099
- const mockRoles = getMockRolesFromCookie(request);
1100
- return request[ENABLE_MOCK_ROLE_KEY] ? mockRoles : void 0;
1101
- });
1102
-
1103
- // src/controllers/permission.controller.ts
1104
- import { Controller, Get, Post, Res, Body } from "@nestjs/common";
1105
- import { ApiOperation, ApiResponse, ApiTags, ApiProperty } from "@nestjs/swagger";
1106
- function _ts_decorate7(decorators, target, key, desc) {
1107
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1108
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1109
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1110
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1111
- }
1112
- __name(_ts_decorate7, "_ts_decorate");
1113
- function _ts_metadata4(k, v) {
1114
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1115
- }
1116
- __name(_ts_metadata4, "_ts_metadata");
1117
- function _ts_param3(paramIndex, decorator) {
1118
- return function(target, key) {
1119
- decorator(target, key, paramIndex);
1120
- };
1121
- }
1122
- __name(_ts_param3, "_ts_param");
1123
- var PermissionDto = class {
1124
- static {
1125
- __name(this, "PermissionDto");
1126
- }
1127
- sub;
1128
- actions;
1129
- id;
1130
- name;
1131
- conditions;
1132
- };
1133
- _ts_decorate7([
1134
- ApiProperty({
1135
- description: "\u8D44\u6E90\u7C7B\u578B",
1136
- example: "task"
1137
- }),
1138
- _ts_metadata4("design:type", String)
1139
- ], PermissionDto.prototype, "sub", void 0);
1140
- _ts_decorate7([
1141
- ApiProperty({
1142
- description: "\u64CD\u4F5C\u7C7B\u578B\u5217\u8868",
1143
- example: [
1144
- "create",
1145
- "read",
1146
- "update",
1147
- "delete"
1148
- ],
1149
- type: [
1150
- String
1151
- ]
1152
- }),
1153
- _ts_metadata4("design:type", Array)
1154
- ], PermissionDto.prototype, "actions", void 0);
1155
- _ts_decorate7([
1156
- ApiProperty({
1157
- description: "\u6743\u9650ID",
1158
- required: false
1159
- }),
1160
- _ts_metadata4("design:type", String)
1161
- ], PermissionDto.prototype, "id", void 0);
1162
- _ts_decorate7([
1163
- ApiProperty({
1164
- description: "\u6743\u9650\u540D\u79F0",
1165
- required: false
1166
- }),
1167
- _ts_metadata4("design:type", String)
1168
- ], PermissionDto.prototype, "name", void 0);
1169
- _ts_decorate7([
1170
- ApiProperty({
1171
- description: "\u6743\u9650\u6761\u4EF6",
1172
- required: false,
1173
- type: "object"
1174
- }),
1175
- _ts_metadata4("design:type", typeof Record === "undefined" ? Object : Record)
1176
- ], PermissionDto.prototype, "conditions", void 0);
1177
- var PermissionResponse = class {
1178
- static {
1179
- __name(this, "PermissionResponse");
1180
- }
1181
- userId;
1182
- roles;
1183
- permissions;
1184
- fetchedAt;
1185
- };
1186
- _ts_decorate7([
1187
- ApiProperty({
1188
- description: "\u7528\u6237ID",
1189
- example: "user123",
1190
- required: false
1191
- }),
1192
- _ts_metadata4("design:type", String)
1193
- ], PermissionResponse.prototype, "userId", void 0);
1194
- _ts_decorate7([
1195
- ApiProperty({
1196
- description: "\u7528\u6237\u89D2\u8272\u5217\u8868",
1197
- example: [
1198
- "admin",
1199
- "user"
1200
- ],
1201
- type: [
1202
- String
1203
- ]
1204
- }),
1205
- _ts_metadata4("design:type", Array)
1206
- ], PermissionResponse.prototype, "roles", void 0);
1207
- _ts_decorate7([
1208
- ApiProperty({
1209
- description: "\u7528\u6237\u6743\u9650\u70B9\u4F4D\u5217\u8868",
1210
- type: [
1211
- PermissionDto
1212
- ]
1213
- }),
1214
- _ts_metadata4("design:type", Array)
1215
- ], PermissionResponse.prototype, "permissions", void 0);
1216
- _ts_decorate7([
1217
- ApiProperty({
1218
- description: "\u6570\u636E\u83B7\u53D6\u65F6\u95F4",
1219
- example: "2025-10-14T00:00:00.000Z"
1220
- }),
1221
- _ts_metadata4("design:type", typeof Date === "undefined" ? Object : Date)
1222
- ], PermissionResponse.prototype, "fetchedAt", void 0);
1223
- var PermissionController = class {
1224
- static {
1225
- __name(this, "PermissionController");
1226
- }
1227
- permissionService;
1228
- constructor(permissionService) {
1229
- this.permissionService = permissionService;
1230
- }
1231
- /**
1232
- * 获取当前用户的权限数据
1233
- *
1234
- * @param userId 当前用户ID(从请求上下文中获取)
1235
- * @returns 用户权限数据
1236
- *
1237
- * @example
1238
- * GET /api/permissions
1239
- *
1240
- * Response:
1241
- * {
1242
- * "userId": "user123",
1243
- * "roles": ["admin", "user"],
1244
- * "permissions": [
1245
- * { "sub": "task", "actions": ["create", "read", "update", "delete"] }
1246
- * ],
1247
- * "fetchedAt": "2025-10-14T00:00:00.000Z"
1248
- * }
1249
- */
1250
- async getUserPermissions(userId, mockRoles) {
1251
- const permissionData = await this.permissionService.getUserPermissions(userId, mockRoles);
1252
- return {
1253
- userId: permissionData?.userId,
1254
- roles: permissionData?.roles || [],
1255
- permissions: permissionData?.permissions || [],
1256
- fetchedAt: permissionData?.fetchedAt || /* @__PURE__ */ new Date()
1257
- };
1258
- }
1259
- /**
1260
- * 开启角色模拟:将传入的 userId 写入 cookie,服务端优先使用该值请求权限
1261
- */
1262
- async enableMock(res, roles) {
1263
- if (!Array.isArray(roles) || roles.length === 0) {
1264
- return {
1265
- success: false,
1266
- message: "roles \u4E0D\u80FD\u4E3A\u7A7A"
1267
- };
1268
- }
1269
- const val = roles.join(",");
1270
- res.cookie(MOCK_ROLES_COOKIE_KEY, val, {
1271
- httpOnly: false,
1272
- sameSite: "lax",
1273
- maxAge: 24 * 60 * 60 * 1e3,
1274
- path: "/"
1275
- });
1276
- return {
1277
- success: true,
1278
- roles
1279
- };
1280
- }
1281
- /**
1282
- * 关闭角色模拟:清除 cookie
1283
- */
1284
- async disableMock(res) {
1285
- res.clearCookie(MOCK_ROLES_COOKIE_KEY, {
1286
- path: "/"
1287
- });
1288
- return {
1289
- success: true
1290
- };
1291
- }
1292
- async getMockRoles(mockRoles, userId) {
1293
- const permissionData = await this.permissionService.getUserPermissions(userId, mockRoles);
1294
- return {
1295
- mocking: !!mockRoles,
1296
- roles: permissionData?.roles || [],
1297
- permissions: permissionData?.permissions || [],
1298
- fetchedAt: permissionData?.fetchedAt || /* @__PURE__ */ new Date(),
1299
- userId
1300
- };
1301
- }
1302
- };
1303
- _ts_decorate7([
1304
- Get(),
1305
- ApiOperation({
1306
- summary: "\u83B7\u53D6\u5F53\u524D\u7528\u6237\u7684\u6743\u9650\u6570\u636E"
1307
- }),
1308
- ApiResponse({
1309
- status: 200,
1310
- description: "\u6210\u529F\u8FD4\u56DE\u7528\u6237\u6743\u9650\u6570\u636E",
1311
- type: PermissionResponse
1312
- }),
1313
- ApiResponse({
1314
- status: 400,
1315
- description: "\u7528\u6237\u672A\u8BA4\u8BC1"
1316
- }),
1317
- _ts_param3(0, UserId()),
1318
- _ts_param3(1, MockRoles()),
1319
- _ts_metadata4("design:type", Function),
1320
- _ts_metadata4("design:paramtypes", [
1321
- String,
1322
- Array
1323
- ]),
1324
- _ts_metadata4("design:returntype", Promise)
1325
- ], PermissionController.prototype, "getUserPermissions", null);
1326
- _ts_decorate7([
1327
- Post("mock/enable"),
1328
- ApiOperation({
1329
- summary: "\u5F00\u542F\u89D2\u8272\u6A21\u62DF\uFF08\u5199\u5165 cookie: mockRoles\uFF09"
1330
- }),
1331
- ApiResponse({
1332
- status: 200,
1333
- description: "\u6A21\u62DF\u5DF2\u5F00\u542F"
1334
- }),
1335
- _ts_param3(0, Res({
1336
- passthrough: true
1337
- })),
1338
- _ts_param3(1, Body("roles")),
1339
- _ts_metadata4("design:type", Function),
1340
- _ts_metadata4("design:paramtypes", [
1341
- typeof Response === "undefined" ? Object : Response,
1342
- Array
1343
- ]),
1344
- _ts_metadata4("design:returntype", Promise)
1345
- ], PermissionController.prototype, "enableMock", null);
1346
- _ts_decorate7([
1347
- Post("mock/disable"),
1348
- ApiOperation({
1349
- summary: "\u5173\u95ED\u89D2\u8272\u6A21\u62DF\uFF08\u6E05\u9664 cookie: mockRoles\uFF09"
1350
- }),
1351
- ApiResponse({
1352
- status: 200,
1353
- description: "\u6A21\u62DF\u5DF2\u5173\u95ED"
1354
- }),
1355
- _ts_param3(0, Res({
1356
- passthrough: true
1357
- })),
1358
- _ts_metadata4("design:type", Function),
1359
- _ts_metadata4("design:paramtypes", [
1360
- typeof Response === "undefined" ? Object : Response
1361
- ]),
1362
- _ts_metadata4("design:returntype", Promise)
1363
- ], PermissionController.prototype, "disableMock", null);
1364
- _ts_decorate7([
1365
- Get("mock/status"),
1366
- ApiOperation({
1367
- summary: "\u83B7\u53D6\u5F53\u524D\u7528\u6237\u7684\u89D2\u8272\u6A21\u62DF\u72B6\u6001"
1368
- }),
1369
- ApiResponse({
1370
- status: 200,
1371
- description: "\u6210\u529F\u8FD4\u56DE\u89D2\u8272\u6A21\u62DF\u6570\u636E"
1372
- }),
1373
- _ts_param3(0, MockRoles()),
1374
- _ts_param3(1, UserId()),
1375
- _ts_metadata4("design:type", Function),
1376
- _ts_metadata4("design:paramtypes", [
1377
- Object,
1378
- String
1379
- ]),
1380
- _ts_metadata4("design:returntype", Promise)
1381
- ], PermissionController.prototype, "getMockRoles", null);
1382
- PermissionController = _ts_decorate7([
1383
- ApiTags("\u6743\u9650\u7BA1\u7406"),
1384
- Controller("api/permissions"),
1385
- _ts_metadata4("design:type", Function),
1386
- _ts_metadata4("design:paramtypes", [
1387
- typeof PermissionService === "undefined" ? Object : PermissionService
1388
- ])
1389
- ], PermissionController);
1390
623
  export {
1391
624
  ANONYMOUS_USER_ID,
1392
625
  AUTHZPAAS_MODULE_OPTIONS,
1393
626
  AbilityFactory,
1394
- AuthZPaasExceptionFilter,
1395
- AuthZPaasGuard,
1396
627
  AuthZPaasModule,
1397
628
  CACHE_CONFIG_TOKEN,
1398
- CanEnv,
1399
- CanPermission,
1400
629
  CanRole,
1401
630
  DEFAULT_LOGIN_PATH,
1402
631
  ENABLE_MOCK_ROLE_KEY,
1403
632
  ENVIRONMENT_KEY,
1404
633
  MOCK_ROLES_COOKIE_KEY,
1405
- MockRoles,
1406
- NEED_LOGIN_KEY,
634
+ NEED_LOGIN_KEY2 as NEED_LOGIN_KEY,
1407
635
  PERMISSIONS_KEY,
1408
636
  PERMISSION_API_CONFIG_TOKEN,
1409
- PermissionController,
1410
637
  PermissionDeniedException,
1411
638
  PermissionDeniedType,
1412
- PermissionDto,
1413
- PermissionResponse,
1414
- PermissionService,
1415
639
  ROLES_KEY,
1416
- ROLE_SUBJECT,
1417
- RolesMiddleware,
1418
- UserId
640
+ ROLE_SUBJECT
1419
641
  };
1420
642
  //# sourceMappingURL=index.js.map