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

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