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

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