@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.cjs CHANGED
@@ -24,173 +24,162 @@ __export(index_exports, {
24
24
  ANONYMOUS_USER_ID: () => ANONYMOUS_USER_ID,
25
25
  AUTHZPAAS_MODULE_OPTIONS: () => AUTHZPAAS_MODULE_OPTIONS,
26
26
  AbilityFactory: () => AbilityFactory,
27
- AuthZPaasExceptionFilter: () => AuthZPaasExceptionFilter,
28
- AuthZPaasGuard: () => AuthZPaasGuard,
29
27
  AuthZPaasModule: () => AuthZPaasModule,
30
28
  CACHE_CONFIG_TOKEN: () => CACHE_CONFIG_TOKEN,
31
- CanEnv: () => CanEnv,
32
- CanPermission: () => CanPermission,
33
29
  CanRole: () => CanRole,
34
30
  DEFAULT_LOGIN_PATH: () => DEFAULT_LOGIN_PATH,
35
31
  ENABLE_MOCK_ROLE_KEY: () => ENABLE_MOCK_ROLE_KEY,
36
32
  ENVIRONMENT_KEY: () => ENVIRONMENT_KEY,
37
33
  MOCK_ROLES_COOKIE_KEY: () => MOCK_ROLES_COOKIE_KEY,
38
- MockRoles: () => MockRoles,
39
- NEED_LOGIN_KEY: () => NEED_LOGIN_KEY,
34
+ NEED_LOGIN_KEY: () => NEED_LOGIN_KEY2,
40
35
  PERMISSIONS_KEY: () => PERMISSIONS_KEY,
41
36
  PERMISSION_API_CONFIG_TOKEN: () => PERMISSION_API_CONFIG_TOKEN,
42
- PermissionController: () => PermissionController,
43
37
  PermissionDeniedException: () => PermissionDeniedException,
44
38
  PermissionDeniedType: () => PermissionDeniedType,
45
- PermissionDto: () => PermissionDto,
46
- PermissionResponse: () => PermissionResponse,
47
- PermissionService: () => PermissionService,
48
39
  ROLES_KEY: () => ROLES_KEY,
49
- ROLE_SUBJECT: () => ROLE_SUBJECT,
50
- RolesMiddleware: () => RolesMiddleware,
51
- UserId: () => UserId
40
+ ROLE_SUBJECT: () => ROLE_SUBJECT
52
41
  });
53
42
  module.exports = __toCommonJS(index_exports);
54
43
 
55
44
  // 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";
45
+ var import_common9 = require("@nestjs/common");
46
+ var import_core4 = require("@nestjs/core");
71
47
 
72
48
  // src/services/permission.service.ts
73
- var import_common3 = require("@nestjs/common");
49
+ var import_common7 = require("@nestjs/common");
74
50
 
75
- // src/utils/memory-cache.ts
76
- var MemoryCache = class {
51
+ // ../nestjs-authnpaas/dist/index.js
52
+ var import_common = require("@nestjs/common");
53
+ var import_core = require("@nestjs/core");
54
+ var import_common2 = require("@nestjs/common");
55
+ var import_core2 = require("@nestjs/core");
56
+ var import_common3 = require("@nestjs/common");
57
+ var import_common4 = require("@nestjs/common");
58
+ var __defProp2 = Object.defineProperty;
59
+ var __name2 = /* @__PURE__ */ __name((target, value) => __defProp2(target, "name", {
60
+ value,
61
+ configurable: true
62
+ }), "__name");
63
+ var AUTHNPAAS_MODULE_OPTIONS = Symbol("AUTHNPAAS_MODULE_OPTIONS");
64
+ var NEED_LOGIN_KEY = "authnpaas:needLogin";
65
+ function _ts_decorate(decorators, target, key, desc) {
66
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
67
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
68
+ 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;
69
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
70
+ }
71
+ __name(_ts_decorate, "_ts_decorate");
72
+ __name2(_ts_decorate, "_ts_decorate");
73
+ function _ts_metadata(k, v) {
74
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
75
+ }
76
+ __name(_ts_metadata, "_ts_metadata");
77
+ __name2(_ts_metadata, "_ts_metadata");
78
+ var AuthNPaasGuard = class {
77
79
  static {
78
- __name(this, "MemoryCache");
80
+ __name(this, "AuthNPaasGuard");
79
81
  }
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;
82
+ static {
83
+ __name2(this, "AuthNPaasGuard");
89
84
  }
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;
85
+ reflector;
86
+ constructor(reflector) {
87
+ this.reflector = reflector;
111
88
  }
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();
89
+ async canActivate(context) {
90
+ const http = context.switchToHttp();
91
+ const request = http.getRequest();
92
+ const response = http.getResponse();
93
+ const { userId, loginUrl } = request.userContext || {};
94
+ const needLoginMeta = this.reflector.getAllAndOverride(NEED_LOGIN_KEY, [
95
+ context.getHandler(),
96
+ context.getClass()
97
+ ]);
98
+ if (needLoginMeta && !userId && loginUrl) {
99
+ response.redirect(302, loginUrl);
100
+ return false;
121
101
  }
122
- const expireAt = Date.now() + this.options.ttl * 1e3;
123
- this.cache.set(key, {
124
- value,
125
- expireAt
126
- });
127
- this.updateAccessOrder(key);
102
+ return true;
128
103
  }
129
- /**
130
- * 删除缓存
131
- */
132
- delete(key) {
133
- this.cache.delete(key);
134
- this.removeFromAccessOrder(key);
104
+ };
105
+ AuthNPaasGuard = _ts_decorate([
106
+ (0, import_common2.Injectable)(),
107
+ _ts_metadata("design:type", Function),
108
+ _ts_metadata("design:paramtypes", [
109
+ typeof import_core2.Reflector === "undefined" ? Object : import_core2.Reflector
110
+ ])
111
+ ], AuthNPaasGuard);
112
+ function _ts_decorate2(decorators, target, key, desc) {
113
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
114
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
115
+ 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;
116
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
117
+ }
118
+ __name(_ts_decorate2, "_ts_decorate2");
119
+ __name2(_ts_decorate2, "_ts_decorate");
120
+ var AuthNPaasModule = class _AuthNPaasModule {
121
+ static {
122
+ __name(this, "_AuthNPaasModule");
135
123
  }
136
- /**
137
- * 清空所有缓存
138
- */
139
- clear() {
140
- this.cache.clear();
141
- this.accessOrder = [];
142
- this.hits = 0;
143
- this.misses = 0;
124
+ static {
125
+ __name2(this, "AuthNPaasModule");
144
126
  }
145
- /**
146
- * 获取缓存统计信息
147
- */
148
- getStats() {
127
+ static forRoot(options) {
149
128
  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
129
+ module: _AuthNPaasModule,
130
+ global: true,
131
+ controllers: [],
132
+ providers: [
133
+ // 配置提供者
134
+ {
135
+ provide: AUTHNPAAS_MODULE_OPTIONS,
136
+ useValue: {
137
+ ...options || {}
138
+ }
139
+ },
140
+ // 核心服务
141
+ import_core.Reflector,
142
+ // 服务提供者
143
+ AuthNPaasGuard,
144
+ // 守卫提供者
145
+ {
146
+ provide: import_core.APP_GUARD,
147
+ useClass: AuthNPaasGuard
148
+ }
149
+ ],
150
+ exports: []
155
151
  };
156
152
  }
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
153
  };
154
+ AuthNPaasModule = _ts_decorate2([
155
+ (0, import_common.Module)({})
156
+ ], AuthNPaasModule);
157
+ var IS_PUBLIC_KEY = "isPublic";
158
+ var Public = /* @__PURE__ */ __name2(() => (0, import_common3.SetMetadata)(IS_PUBLIC_KEY, true), "Public");
159
+
160
+ // src/const.ts
161
+ var ANONYMOUS_USER_ID = "anonymous_user_id";
162
+ var PERMISSION_API_CONFIG_TOKEN = Symbol("PERMISSION_API_CONFIG");
163
+ var CACHE_CONFIG_TOKEN = Symbol("CACHE_CONFIG");
164
+ var AUTHZPAAS_MODULE_OPTIONS = Symbol("AUTHZPAAS_MODULE_OPTIONS");
165
+ var ROLES_KEY = "authzpaas:roles";
166
+ var PERMISSIONS_KEY = "authzpaas:permissions";
167
+ var ENVIRONMENT_KEY = "authzpaas:environment";
168
+ var NEED_LOGIN_KEY2 = "authzpaas:needLogin";
169
+ var DEFAULT_LOGIN_PATH = "/login";
170
+ var MOCK_ROLES_COOKIE_KEY = "mockRoles";
171
+ var ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
183
172
 
184
173
  // src/casl/ability.factory.ts
185
- var import_common = require("@nestjs/common");
174
+ var import_common5 = require("@nestjs/common");
186
175
  var import_ability = require("@casl/ability");
187
- function _ts_decorate(decorators, target, key, desc) {
176
+ function _ts_decorate3(decorators, target, key, desc) {
188
177
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
189
178
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
190
179
  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
180
  return c > 3 && r && Object.defineProperty(target, key, r), r;
192
181
  }
193
- __name(_ts_decorate, "_ts_decorate");
182
+ __name(_ts_decorate3, "_ts_decorate");
194
183
  var ROLE_SUBJECT = "@role";
195
184
  var AbilityFactory = class {
196
185
  static {
@@ -201,33 +190,26 @@ var AbilityFactory = class {
201
190
  */
202
191
  createForUser(permissionData) {
203
192
  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
193
  for (const role of permissionData.roles) {
211
194
  can(role, ROLE_SUBJECT);
212
195
  }
213
196
  return build();
214
197
  }
215
198
  };
216
- AbilityFactory = _ts_decorate([
217
- (0, import_common.Injectable)()
199
+ AbilityFactory = _ts_decorate3([
200
+ (0, import_common5.Injectable)()
218
201
  ], AbilityFactory);
219
202
 
220
203
  // src/exceptions/permission-denied.exception.ts
221
- var import_common2 = require("@nestjs/common");
204
+ var import_common6 = require("@nestjs/common");
222
205
  var PermissionDeniedType = /* @__PURE__ */ (function(PermissionDeniedType2) {
223
206
  PermissionDeniedType2["UNAUTHENTICATED"] = "UNAUTHENTICATED";
224
207
  PermissionDeniedType2["ROLE_REQUIRED"] = "ROLE_REQUIRED";
225
208
  PermissionDeniedType2["PERMISSION_REQUIRED"] = "PERMISSION_REQUIRED";
226
- PermissionDeniedType2["ENVIRONMENT_REQUIRED"] = "ENVIRONMENT_REQUIRED";
227
209
  PermissionDeniedType2["PERMISSION_CONFIG_QUERY_FAILED"] = "PERMISSION_CONFIG_QUERY_FAILED";
228
210
  return PermissionDeniedType2;
229
211
  })({});
230
- var PermissionDeniedException = class _PermissionDeniedException extends import_common2.HttpException {
212
+ var PermissionDeniedException = class _PermissionDeniedException extends import_common6.HttpException {
231
213
  static {
232
214
  __name(this, "PermissionDeniedException");
233
215
  }
@@ -301,30 +283,20 @@ var PermissionDeniedException = class _PermissionDeniedException extends import_
301
283
  }
302
284
  });
303
285
  }
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
286
  };
315
287
 
316
288
  // src/services/permission.service.ts
317
- function _ts_decorate2(decorators, target, key, desc) {
289
+ function _ts_decorate4(decorators, target, key, desc) {
318
290
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
319
291
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
320
292
  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
293
  return c > 3 && r && Object.defineProperty(target, key, r), r;
322
294
  }
323
- __name(_ts_decorate2, "_ts_decorate");
324
- function _ts_metadata(k, v) {
295
+ __name(_ts_decorate4, "_ts_decorate");
296
+ function _ts_metadata2(k, v) {
325
297
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
326
298
  }
327
- __name(_ts_metadata, "_ts_metadata");
299
+ __name(_ts_metadata2, "_ts_metadata");
328
300
  function _ts_param(paramIndex, decorator) {
329
301
  return function(target, key) {
330
302
  decorator(target, key, paramIndex);
@@ -337,91 +309,50 @@ var PermissionService = class _PermissionService {
337
309
  }
338
310
  apiConfig;
339
311
  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) {
312
+ logger = new import_common7.Logger(_PermissionService.name);
313
+ constructor(apiConfig, abilityFactory) {
346
314
  this.apiConfig = apiConfig;
347
315
  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
316
  }
355
317
  /**
356
- * 构建权限/Ability 缓存 key
357
- * - 若存在模拟角色:按角色集合排序拼接 + 用户维度
358
- * - 否则按 userId/匿名用户
318
+ * 获取用户权限数据
359
319
  */
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
- }
369
- /**
370
- * 获取用户权限数据(带缓存)
371
- */
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`);
320
+ async getUserPermissions(requestDto) {
389
321
  const requestPromise = (async () => {
322
+ const userId = requestDto.userId || ANONYMOUS_USER_ID;
390
323
  try {
391
- const permissionData = mockRoles && mockRoles.length > 0 ? await this.getPermissionsByMockRoles(userId, mockRoles) : await this.fetchFromApi(userId);
324
+ const permissionData = await this.fetchFromApi(requestDto);
392
325
  const dataWithTimestamp = {
393
326
  ...permissionData,
394
327
  fetchedAt: /* @__PURE__ */ new Date()
395
328
  };
396
- const ability = this.abilityFactory.createForUser(dataWithTimestamp);
397
- this.cache.set(key, {
398
- permissionData: dataWithTimestamp,
399
- ability
400
- });
401
329
  return dataWithTimestamp;
402
330
  } catch (error) {
403
- this.logger.error(`Failed to fetch permissions for key ${key}:`, error);
331
+ this.logger.error(`Failed to fetch permissions for user ${userId}:`, error);
404
332
  throw error;
405
- } finally {
406
- this.pendingRequests.delete(key);
407
333
  }
408
334
  })();
409
- this.pendingRequests.set(key, requestPromise);
410
335
  return requestPromise;
411
336
  }
412
337
  /**
413
338
  * 从 API 获取权限数据
414
339
  * 内置实现,用户无需配置
415
340
  */
416
- async fetchFromApi(userId) {
417
- const { baseUrl, apiToken, endpoint, headers = {}, timeout = 5e3 } = this.apiConfig || {};
418
- const url = `${baseUrl}${endpoint}${userId ? `?userId=${userId}` : ""}`;
341
+ async fetchFromApi(requestDto) {
342
+ const { timeout = 5e3 } = this.apiConfig || {};
343
+ const { baseUrl, userId, appId, cookies, csrfToken } = requestDto;
344
+ const url = `${baseUrl}/api/v1/permission/apps/${appId}/roles`;
419
345
  const requestHeaders = {
420
- "Content-Type": "application/json",
421
- ...headers
346
+ "Content-Type": "application/json"
422
347
  };
423
- if (apiToken) {
424
- requestHeaders["Authorization"] = `Bearer ${apiToken}`;
348
+ if (cookies) {
349
+ const cookieString = Object.entries(cookies).map(([key, value]) => `${key}=${value}`).join("; ");
350
+ if (cookieString) {
351
+ requestHeaders.Cookie = cookieString;
352
+ }
353
+ }
354
+ if (csrfToken) {
355
+ requestHeaders["X-Suda-Csrf-Token"] = csrfToken;
425
356
  }
426
357
  const controller = new AbortController();
427
358
  const timeoutId = setTimeout(() => controller.abort(), timeout);
@@ -438,14 +369,14 @@ var PermissionService = class _PermissionService {
438
369
  cause: error,
439
370
  type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
440
371
  message: error.message
441
- }, import_common3.HttpStatus.INTERNAL_SERVER_ERROR);
372
+ }, import_common7.HttpStatus.INTERNAL_SERVER_ERROR);
442
373
  }
443
374
  const data = await response.json();
444
- const roles = (data.roles || []).map((role) => typeof role === "string" ? role : role.name);
445
375
  return {
446
376
  userId,
447
- roles,
448
- permissions: data.permissions || [],
377
+ roles: data.role_list || [],
378
+ // TODO: 基于权限点位设置能力
379
+ // permissions: data.permissions || [],
449
380
  fetchedAt: /* @__PURE__ */ new Date()
450
381
  };
451
382
  } catch (error) {
@@ -458,83 +389,31 @@ var PermissionService = class _PermissionService {
458
389
  cause: err,
459
390
  type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
460
391
  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
- }
392
+ }, import_common7.HttpStatus.INTERNAL_SERVER_ERROR);
393
+ }
394
+ }
395
+ // /**
396
+ // * 获取用户的 Ability 实例(带缓存)
397
+ // * @param userId 用户ID
398
+ // * @returns CASL Ability 实例
399
+ // */
400
+ // private async getUserAbility(
401
+ // userId?: string,
402
+ // mockRoles?: string[]
403
+ // ): Promise<AppAbility> {
404
+ // // 计算缓存 key
405
+ // const key = this.buildCacheKey(userId, mockRoles);
406
+ // // 尝试从缓存获取
407
+ // const cached = this.cache.get(key);
408
+ // if (cached) {
409
+ // return cached.ability;
410
+ // }
411
+ // // 缓存未命中,调用 getUserPermissions 会创建并缓存
412
+ // await this.getUserPermissions(userId, mockRoles);
413
+ // // 再次从缓存获取(此时一定存在)
414
+ // const newCached = this.cache.get(key);
415
+ // return newCached!.ability;
416
+ // }
538
417
  /**
539
418
  * 检查角色要求
540
419
  * 使用 CASL Ability 统一鉴权方式
@@ -543,16 +422,23 @@ var PermissionService = class _PermissionService {
543
422
  * @returns 用户权限数据
544
423
  * @throws PermissionDeniedException 当角色不满足时
545
424
  */
546
- async checkRoles(requirement, userId, mockRoles) {
547
- const permissionData = await this.getUserPermissions(userId, mockRoles);
425
+ async checkRoles(requirement, userContext) {
426
+ const userId = userContext?.userId || ANONYMOUS_USER_ID;
427
+ const permissionData = await this.getUserPermissions({
428
+ baseUrl: userContext?.baseUrl || "",
429
+ userId,
430
+ appId: userContext?.appId || "",
431
+ cookies: userContext?.cookies || {},
432
+ csrfToken: userContext?.csrfToken || ""
433
+ });
548
434
  if (!permissionData) {
549
435
  throw new PermissionDeniedException({
550
436
  cause: new Error("Permission data fetch api is not configured"),
551
437
  type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
552
438
  message: "Permission data fetch api is not configured"
553
- }, import_common3.HttpStatus.BAD_REQUEST);
439
+ }, import_common7.HttpStatus.BAD_REQUEST);
554
440
  }
555
- const ability = await this.getUserAbility(userId, mockRoles);
441
+ const ability = this.abilityFactory.createForUser(permissionData);
556
442
  const { roles, and } = requirement;
557
443
  const checkResults = roles.map((role) => ability.can(role, ROLE_SUBJECT));
558
444
  const hasRole = and ? checkResults.every((result) => result) : checkResults.some((result) => result);
@@ -563,371 +449,70 @@ var PermissionService = class _PermissionService {
563
449
  }
564
450
  return permissionData;
565
451
  }
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
452
  };
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", [
453
+ PermissionService = _ts_decorate4([
454
+ (0, import_common7.Injectable)(),
455
+ Public(),
456
+ _ts_param(0, (0, import_common7.Inject)(PERMISSION_API_CONFIG_TOKEN)),
457
+ _ts_metadata2("design:type", Function),
458
+ _ts_metadata2("design:paramtypes", [
625
459
  typeof PermissionApiConfig === "undefined" ? Object : PermissionApiConfig,
626
- typeof CacheConfig === "undefined" ? Object : CacheConfig,
627
460
  typeof AbilityFactory === "undefined" ? Object : AbilityFactory
628
461
  ])
629
462
  ], PermissionService);
630
463
 
631
464
  // 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) {
465
+ var import_common8 = require("@nestjs/common");
466
+ var import_core3 = require("@nestjs/core");
467
+ function _ts_decorate5(decorators, target, key, desc) {
644
468
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
645
469
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
646
470
  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
471
  return c > 3 && r && Object.defineProperty(target, key, r), r;
648
472
  }
649
- __name(_ts_decorate3, "_ts_decorate");
650
- function _ts_metadata2(k, v) {
473
+ __name(_ts_decorate5, "_ts_decorate");
474
+ function _ts_metadata3(k, v) {
651
475
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
652
476
  }
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");
477
+ __name(_ts_metadata3, "_ts_metadata");
660
478
  var AuthZPaasGuard = class {
661
479
  static {
662
480
  __name(this, "AuthZPaasGuard");
663
481
  }
664
482
  reflector;
665
483
  permissionService;
666
- moduleOptions;
667
- constructor(reflector, permissionService, moduleOptions) {
484
+ constructor(reflector, permissionService) {
668
485
  this.reflector = reflector;
669
486
  this.permissionService = permissionService;
670
- this.moduleOptions = moduleOptions;
671
487
  }
672
488
  async canActivate(context) {
673
489
  const http = context.switchToHttp();
674
490
  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;
491
+ const userContext = request.userContext;
678
492
  const checkRoleRequirement = this.reflector.getAllAndOverride(ROLES_KEY, [
679
493
  context.getHandler(),
680
494
  context.getClass()
681
495
  ]);
682
496
  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);
497
+ await this.checkRoleRequirement(checkRoleRequirement, userContext);
699
498
  }
700
499
  return true;
701
500
  }
702
501
  /**
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
502
  * 检查角色要求
753
503
  */
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
- });
504
+ async checkRoleRequirement(requirement, userContext) {
505
+ return this.permissionService.checkRoles(requirement, userContext);
825
506
  }
826
507
  };
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
835
- ])
836
- ], AuthZPaasGuard);
837
-
838
- // src/middlewares/roles.middleware.ts
839
- var import_common5 = require("@nestjs/common");
840
- function _ts_decorate4(decorators, target, key, desc) {
841
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
842
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
843
- 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
- return c > 3 && r && Object.defineProperty(target, key, r), r;
845
- }
846
- __name(_ts_decorate4, "_ts_decorate");
847
- function _ts_metadata3(k, v) {
848
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
849
- }
850
- __name(_ts_metadata3, "_ts_metadata");
851
- var RolesMiddleware = class _RolesMiddleware {
852
- static {
853
- __name(this, "RolesMiddleware");
854
- }
855
- permissionService;
856
- logger = new import_common5.Logger(_RolesMiddleware.name);
857
- constructor(permissionService) {
858
- this.permissionService = permissionService;
859
- }
860
- async use(req, _res, next) {
861
- try {
862
- const userId = req.userContext?.userId;
863
- const mockRoles = req[ENABLE_MOCK_ROLE_KEY] ? getMockRolesFromCookie(req) : void 0;
864
- this.logger.debug(`Fetching roles for user: ${userId}`);
865
- const permissionData = await this.permissionService.getUserPermissions(userId, mockRoles);
866
- let roles;
867
- if (permissionData) {
868
- roles = permissionData.roles;
869
- }
870
- req.userContext.userRoles = roles;
871
- req.userContext.userId = userId;
872
- this.logger.debug(`User ${userId} roles loaded: [${roles?.join(", ")}]`);
873
- next();
874
- } catch (error) {
875
- this.logger.warn(`Failed to fetch roles for request: ${error instanceof Error ? error.message : "Unknown error"}`);
876
- next();
877
- }
878
- }
879
- };
880
- RolesMiddleware = _ts_decorate4([
881
- (0, import_common5.Injectable)(),
508
+ AuthZPaasGuard = _ts_decorate5([
509
+ (0, import_common8.Injectable)(),
882
510
  _ts_metadata3("design:type", Function),
883
511
  _ts_metadata3("design:paramtypes", [
512
+ typeof import_core3.Reflector === "undefined" ? Object : import_core3.Reflector,
884
513
  typeof PermissionService === "undefined" ? Object : PermissionService
885
514
  ])
886
- ], RolesMiddleware);
887
-
888
- // src/filters/authzpaas-exception.filter.ts
889
- var import_common6 = require("@nestjs/common");
890
- function _ts_decorate5(decorators, target, key, desc) {
891
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
892
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
893
- 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
- return c > 3 && r && Object.defineProperty(target, key, r), r;
895
- }
896
- __name(_ts_decorate5, "_ts_decorate");
897
- var AuthZPaasExceptionFilter = class {
898
- static {
899
- __name(this, "AuthZPaasExceptionFilter");
900
- }
901
- catch(exception, host) {
902
- const ctx = host.switchToHttp();
903
- const response = ctx.getResponse();
904
- const status = exception.getStatus();
905
- const exceptionResponse = exception.getResponse();
906
- const errorResponse = {
907
- statusCode: status,
908
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
909
- cause: exception.cause,
910
- type: exception.type,
911
- message: typeof exceptionResponse === "string" ? exceptionResponse : exceptionResponse.message || "\u6743\u9650\u4E0D\u8DB3"
912
- };
913
- if (exception.details.requiredRoles) {
914
- errorResponse.requiredRoles = exception.details.requiredRoles;
915
- }
916
- if (exception.details.requiredPermissions) {
917
- errorResponse.requiredPermissions = exception.details.requiredPermissions;
918
- }
919
- if (exception.details.environmentRequirement) {
920
- errorResponse.environmentRequirement = exception.details.environmentRequirement;
921
- }
922
- if (exception.details.metadata) {
923
- errorResponse.metadata = exception.details.metadata;
924
- }
925
- response.status(status).json(errorResponse);
926
- }
927
- };
928
- AuthZPaasExceptionFilter = _ts_decorate5([
929
- (0, import_common6.Catch)(PermissionDeniedException)
930
- ], AuthZPaasExceptionFilter);
515
+ ], AuthZPaasGuard);
931
516
 
932
517
  // src/authzpaas.module.ts
933
518
  function _ts_decorate6(decorators, target, key, desc) {
@@ -942,53 +527,38 @@ var AuthZPaasModule = class _AuthZPaasModule {
942
527
  __name(this, "AuthZPaasModule");
943
528
  }
944
529
  static forRoot(options) {
945
- const { permissionApi, cache = {
946
- ttl: 300,
947
- max: 1e3,
948
- enabled: true
949
- }, isGlobal = true } = options;
530
+ const { permissionApi } = options;
950
531
  return {
951
532
  module: _AuthZPaasModule,
952
- global: isGlobal,
533
+ global: true,
953
534
  controllers: [],
954
535
  providers: [
955
536
  // 配置提供者
956
537
  {
957
538
  provide: AUTHZPAAS_MODULE_OPTIONS,
958
539
  useValue: {
959
- ...options,
960
- loginPath: options.loginPath || DEFAULT_LOGIN_PATH
540
+ ...options
961
541
  }
962
542
  },
963
543
  {
964
544
  provide: PERMISSION_API_CONFIG_TOKEN,
965
545
  useValue: permissionApi
966
546
  },
967
- {
968
- provide: CACHE_CONFIG_TOKEN,
969
- useValue: cache
970
- },
971
547
  // 核心服务
972
- import_core2.Reflector,
548
+ import_core4.Reflector,
973
549
  // 服务提供者
974
550
  PermissionService,
975
551
  AbilityFactory,
976
552
  AuthZPaasGuard,
977
- RolesMiddleware,
978
553
  // 守卫提供者
979
554
  {
980
- provide: import_core2.APP_GUARD,
555
+ provide: import_core4.APP_GUARD,
981
556
  useClass: AuthZPaasGuard
982
- },
983
- {
984
- provide: import_core2.APP_FILTER,
985
- useClass: AuthZPaasExceptionFilter
986
557
  }
987
558
  ],
988
559
  exports: [
989
560
  PermissionService,
990
- AbilityFactory,
991
- RolesMiddleware
561
+ AbilityFactory
992
562
  ]
993
563
  };
994
564
  }
@@ -1023,10 +593,10 @@ var AuthZPaasModule = class _AuthZPaasModule {
1023
593
  * ```
1024
594
  */
1025
595
  static forRootAsync(options) {
1026
- const { imports = [], inject = [], useFactory, isGlobal = true } = options;
596
+ const { imports = [], inject = [], useFactory } = options;
1027
597
  return {
1028
598
  module: _AuthZPaasModule,
1029
- global: isGlobal,
599
+ global: true,
1030
600
  imports,
1031
601
  controllers: [],
1032
602
  providers: [
@@ -1046,51 +616,31 @@ var AuthZPaasModule = class _AuthZPaasModule {
1046
616
  AUTHZPAAS_MODULE_OPTIONS
1047
617
  ]
1048
618
  },
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
619
  // 核心服务
1064
- import_core2.Reflector,
620
+ import_core4.Reflector,
1065
621
  // 服务提供者
1066
622
  PermissionService,
1067
623
  AbilityFactory,
1068
624
  AuthZPaasGuard,
1069
- RolesMiddleware,
1070
625
  // 守卫提供者
1071
626
  {
1072
- provide: import_core2.APP_GUARD,
627
+ provide: import_core4.APP_GUARD,
1073
628
  useClass: AuthZPaasGuard
1074
- },
1075
- {
1076
- provide: import_core2.APP_FILTER,
1077
- useClass: AuthZPaasExceptionFilter
1078
629
  }
1079
630
  ],
1080
631
  exports: [
1081
632
  PermissionService,
1082
- AbilityFactory,
1083
- RolesMiddleware
633
+ AbilityFactory
1084
634
  ]
1085
635
  };
1086
636
  }
1087
637
  };
1088
638
  AuthZPaasModule = _ts_decorate6([
1089
- (0, import_common7.Module)({})
639
+ (0, import_common9.Module)({})
1090
640
  ], AuthZPaasModule);
1091
641
 
1092
642
  // src/decorators/can-role.decorator.ts
1093
- var import_common8 = require("@nestjs/common");
643
+ var import_common10 = require("@nestjs/common");
1094
644
  var CanRole = /* @__PURE__ */ __name((role, and = false) => {
1095
645
  let requirement;
1096
646
  if (!Array.isArray(role) && typeof role === "string") {
@@ -1108,365 +658,26 @@ var CanRole = /* @__PURE__ */ __name((role, and = false) => {
1108
658
  } else {
1109
659
  throw new Error("Invalid CanRole parameter: " + JSON.stringify(role));
1110
660
  }
1111
- return (0, import_common8.SetMetadata)(ROLES_KEY, requirement);
661
+ return (0, import_common10.SetMetadata)(ROLES_KEY, requirement);
1112
662
  }, "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
663
  // Annotate the CommonJS export names for ESM import in node:
1442
664
  0 && (module.exports = {
1443
665
  ANONYMOUS_USER_ID,
1444
666
  AUTHZPAAS_MODULE_OPTIONS,
1445
667
  AbilityFactory,
1446
- AuthZPaasExceptionFilter,
1447
- AuthZPaasGuard,
1448
668
  AuthZPaasModule,
1449
669
  CACHE_CONFIG_TOKEN,
1450
- CanEnv,
1451
- CanPermission,
1452
670
  CanRole,
1453
671
  DEFAULT_LOGIN_PATH,
1454
672
  ENABLE_MOCK_ROLE_KEY,
1455
673
  ENVIRONMENT_KEY,
1456
674
  MOCK_ROLES_COOKIE_KEY,
1457
- MockRoles,
1458
675
  NEED_LOGIN_KEY,
1459
676
  PERMISSIONS_KEY,
1460
677
  PERMISSION_API_CONFIG_TOKEN,
1461
- PermissionController,
1462
678
  PermissionDeniedException,
1463
679
  PermissionDeniedType,
1464
- PermissionDto,
1465
- PermissionResponse,
1466
- PermissionService,
1467
680
  ROLES_KEY,
1468
- ROLE_SUBJECT,
1469
- RolesMiddleware,
1470
- UserId
681
+ ROLE_SUBJECT
1471
682
  });
1472
683
  //# sourceMappingURL=index.cjs.map