@lark-apaas/nestjs-authzpaas 0.1.0-alpha.1 → 0.1.0-alpha.11
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/README.md +0 -253
- package/dist/index.cjs +35 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -98
- package/dist/index.d.ts +6 -98
- package/dist/index.js +31 -157
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -230,257 +230,6 @@ export class SensitiveController {
|
|
|
230
230
|
}
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
-
### 2. CanPermission - 权限检查
|
|
234
|
-
|
|
235
|
-
使用 `@CanPermission()` 装饰器检查用户对特定资源的操作权限。
|
|
236
|
-
|
|
237
|
-
#### 示例 1: 单个操作检查
|
|
238
|
-
|
|
239
|
-
```typescript
|
|
240
|
-
import { Controller, Get } from '@nestjs/common';
|
|
241
|
-
import { CanPermission } from '@lark-apaas/nestjs-authzpaas';
|
|
242
|
-
|
|
243
|
-
@Controller('demo')
|
|
244
|
-
export class DemoController {
|
|
245
|
-
// 需要对 User 资源有 read 权限
|
|
246
|
-
@CanPermission([{ actions: ['read'], subject: 'User' }])
|
|
247
|
-
@Get('read-user')
|
|
248
|
-
readUser() {
|
|
249
|
-
return {
|
|
250
|
-
message: '✅ 用户读取成功(需要 read 权限)',
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// 需要对 User 资源有 create 权限
|
|
255
|
-
@CanPermission([{ actions: ['create'], subject: 'User' }])
|
|
256
|
-
@Get('create-user')
|
|
257
|
-
createUser() {
|
|
258
|
-
return {
|
|
259
|
-
message: '✅ 用户创建成功(需要 create 权限)',
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
#### 示例 2: 多个操作检查(AND 逻辑,默认)
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
@Controller('articles')
|
|
269
|
-
export class ArticleController {
|
|
270
|
-
// 需要同时拥有 read 和 update 权限
|
|
271
|
-
@CanPermission([{
|
|
272
|
-
actions: ['read', 'update'],
|
|
273
|
-
subject: 'Article',
|
|
274
|
-
requireAll: true // 默认为 true,可省略
|
|
275
|
-
}])
|
|
276
|
-
@Get('publish')
|
|
277
|
-
publish() {
|
|
278
|
-
return '发布文章';
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
#### 示例 3: 多个操作检查(OR 逻辑)
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
@Controller('articles')
|
|
287
|
-
export class ArticleController {
|
|
288
|
-
// 拥有 read 或 preview 任一权限即可
|
|
289
|
-
@CanPermission([{
|
|
290
|
-
actions: ['read', 'preview'],
|
|
291
|
-
subject: 'Article',
|
|
292
|
-
requireAll: false // OR 逻辑
|
|
293
|
-
}])
|
|
294
|
-
@Get('preview')
|
|
295
|
-
preview() {
|
|
296
|
-
return '预览文章';
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
#### 示例 4: 多个资源权限检查
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
@Controller('articles')
|
|
305
|
-
export class ArticleController {
|
|
306
|
-
// 需要同时满足:能读文章 AND 能创建评论
|
|
307
|
-
@CanPermission([
|
|
308
|
-
{ actions: ['read'], subject: 'Article' },
|
|
309
|
-
{ actions: ['create'], subject: 'Comment' }
|
|
310
|
-
])
|
|
311
|
-
@Get('comment')
|
|
312
|
-
addComment() {
|
|
313
|
-
return '添加评论';
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// 需要同时满足:能读文章 AND (能更新或删除评论)
|
|
317
|
-
@CanPermission([
|
|
318
|
-
{ actions: ['read'], subject: 'Article' },
|
|
319
|
-
{ actions: ['update', 'delete'], subject: 'Comment', requireAll: false }
|
|
320
|
-
])
|
|
321
|
-
@Get('manage-comment')
|
|
322
|
-
manageComment() {
|
|
323
|
-
return '管理评论';
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### 3. UserId - 获取用户ID
|
|
329
|
-
|
|
330
|
-
使用 `@UserId()` 参数装饰器获取当前用户ID。
|
|
331
|
-
|
|
332
|
-
#### 示例 1: 基本用法
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
import { Controller, Get } from '@nestjs/common';
|
|
336
|
-
import { UserId } from '@lark-apaas/nestjs-authzpaas';
|
|
337
|
-
|
|
338
|
-
@Controller('demo')
|
|
339
|
-
export class DemoController {
|
|
340
|
-
@Get('profile')
|
|
341
|
-
getProfile(@UserId() userId: string) {
|
|
342
|
-
return {
|
|
343
|
-
message: '获取用户资料',
|
|
344
|
-
userId,
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
#### 示例 2: 结合 PermissionService 使用
|
|
351
|
-
|
|
352
|
-
```typescript
|
|
353
|
-
import { Controller, Get } from '@nestjs/common';
|
|
354
|
-
import { UserId, PermissionService } from '@lark-apaas/nestjs-authzpaas';
|
|
355
|
-
|
|
356
|
-
@Controller('demo')
|
|
357
|
-
export class DemoController {
|
|
358
|
-
constructor(private readonly permissionService: PermissionService) {}
|
|
359
|
-
|
|
360
|
-
@Get('check-permission')
|
|
361
|
-
async checkPermission(@UserId() userId: string) {
|
|
362
|
-
// 手动检查权限
|
|
363
|
-
const hasPermission = await this.permissionService.checkPermissions(
|
|
364
|
-
[{ actions: ['read'], subject: 'User' }],
|
|
365
|
-
userId
|
|
366
|
-
);
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
message: '权限检查成功',
|
|
370
|
-
userId,
|
|
371
|
-
hasPermission,
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
#### 示例 3: 使用 CASL Ability
|
|
378
|
-
|
|
379
|
-
```typescript
|
|
380
|
-
import { Controller, Get } from '@nestjs/common';
|
|
381
|
-
import { UserId, PermissionService, ROLE_SUBJECT } from '@lark-apaas/nestjs-authzpaas';
|
|
382
|
-
|
|
383
|
-
@Controller('demo')
|
|
384
|
-
export class DemoController {
|
|
385
|
-
constructor(private readonly permissionService: PermissionService) {}
|
|
386
|
-
|
|
387
|
-
@Get('ability')
|
|
388
|
-
async getAbility(@UserId() userId: string) {
|
|
389
|
-
const ability = await this.permissionService.getAbility(userId);
|
|
390
|
-
|
|
391
|
-
// 使用 CASL Ability 检查权限
|
|
392
|
-
const canReadUser = ability.can('read', 'User');
|
|
393
|
-
const canWriteTask = ability.can('write', 'Task');
|
|
394
|
-
const isAdmin = ability.can('admin', ROLE_SUBJECT);
|
|
395
|
-
|
|
396
|
-
return {
|
|
397
|
-
userId,
|
|
398
|
-
permissions: {
|
|
399
|
-
canReadUser,
|
|
400
|
-
canWriteTask,
|
|
401
|
-
isAdmin,
|
|
402
|
-
},
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
### 4. MockRoles - 角色模拟
|
|
409
|
-
|
|
410
|
-
使用 `@MockRoles()` 参数装饰器获取模拟角色,仅在 `enableMockRole: true` 时有效。
|
|
411
|
-
|
|
412
|
-
#### 示例 1: 基本用法
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
import { Controller, Get } from '@nestjs/common';
|
|
416
|
-
import { MockRoles } from '@lark-apaas/nestjs-authzpaas';
|
|
417
|
-
|
|
418
|
-
@Controller('demo')
|
|
419
|
-
export class DemoController {
|
|
420
|
-
@Get('mock-roles')
|
|
421
|
-
getMockRoles(@MockRoles() mockRoles: string[]) {
|
|
422
|
-
return {
|
|
423
|
-
message: '获取模拟角色',
|
|
424
|
-
mockRoles: mockRoles || [],
|
|
425
|
-
hasMockRoles: !!mockRoles,
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
#### 示例 2: 结合权限检查
|
|
432
|
-
|
|
433
|
-
```typescript
|
|
434
|
-
@Controller('admin')
|
|
435
|
-
export class AdminController {
|
|
436
|
-
@Get('test')
|
|
437
|
-
@CanRole(['admin']) // 会优先使用模拟角色进行验证
|
|
438
|
-
testWithMockRoles(@MockRoles() mockRoles: string[]) {
|
|
439
|
-
return {
|
|
440
|
-
message: '管理员测试接口',
|
|
441
|
-
mockRoles,
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
### 5. 装饰器组合使用
|
|
448
|
-
|
|
449
|
-
可以组合使用多个装饰器实现复杂的鉴权需求。
|
|
450
|
-
|
|
451
|
-
#### 示例 1: 角色 + 权限
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
import { Controller, Get } from '@nestjs/common';
|
|
455
|
-
import { CanRole, CanPermission } from '@lark-apaas/nestjs-authzpaas';
|
|
456
|
-
|
|
457
|
-
@Controller('posts')
|
|
458
|
-
export class PostController {
|
|
459
|
-
// 需要 editor 角色 + 对 Post 有 delete 权限
|
|
460
|
-
@CanRole(['editor'])
|
|
461
|
-
@CanPermission([{ actions: ['delete'], subject: 'Post' }])
|
|
462
|
-
@Get('delete')
|
|
463
|
-
delete() {
|
|
464
|
-
return '删除帖子';
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
#### 示例 2: 多层权限检查
|
|
470
|
-
|
|
471
|
-
```typescript
|
|
472
|
-
@Controller('tasks')
|
|
473
|
-
export class TasksController {
|
|
474
|
-
// 需要 admin 或 manager 角色 + Task 的 manage 权限
|
|
475
|
-
@CanRole(['admin', 'manager'])
|
|
476
|
-
@CanPermission([{ actions: ['manage'], subject: 'Task' }])
|
|
477
|
-
@Get('manage')
|
|
478
|
-
manageTasks() {
|
|
479
|
-
return '管理任务';
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
```
|
|
483
|
-
|
|
484
233
|
## 核心组件
|
|
485
234
|
|
|
486
235
|
> 📚 **核心组件是装饰器的底层实现**,了解核心组件有助于深入理解权限系统的工作原理。
|
|
@@ -491,8 +240,6 @@ export class TasksController {
|
|
|
491
240
|
|
|
492
241
|
1. **提取用户ID**: 从 `req.userContext.userId` 中提取用户ID
|
|
493
242
|
2. **角色检查**: 如果使用了 `@CanRole()`,检查用户角色
|
|
494
|
-
3. **权限检查**: 如果使用了 `@CanPermission()`,检查用户权限
|
|
495
|
-
4. **环境检查**: 如果使用了 `@RequireEnvironment()`,检查环境条件
|
|
496
243
|
5. **注入权限数据**: 将权限数据附加到 `req.userPermissions`
|
|
497
244
|
|
|
498
245
|
**工作流程**:
|
package/dist/index.cjs
CHANGED
|
@@ -24,29 +24,20 @@ __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
27
|
AuthZPaasGuard: () => AuthZPaasGuard,
|
|
29
28
|
AuthZPaasModule: () => AuthZPaasModule,
|
|
30
|
-
CACHE_CONFIG_TOKEN: () => CACHE_CONFIG_TOKEN,
|
|
31
29
|
CanRole: () => CanRole,
|
|
32
|
-
DEFAULT_LOGIN_PATH: () => DEFAULT_LOGIN_PATH,
|
|
33
|
-
ENABLE_MOCK_ROLE_KEY: () => ENABLE_MOCK_ROLE_KEY,
|
|
34
|
-
ENVIRONMENT_KEY: () => ENVIRONMENT_KEY,
|
|
35
|
-
MOCK_ROLES_COOKIE_KEY: () => MOCK_ROLES_COOKIE_KEY,
|
|
36
|
-
NEED_LOGIN_KEY: () => NEED_LOGIN_KEY2,
|
|
37
|
-
PERMISSIONS_KEY: () => PERMISSIONS_KEY,
|
|
38
30
|
PERMISSION_API_CONFIG_TOKEN: () => PERMISSION_API_CONFIG_TOKEN,
|
|
39
31
|
PermissionDeniedException: () => PermissionDeniedException,
|
|
40
32
|
PermissionDeniedType: () => PermissionDeniedType,
|
|
41
33
|
PermissionService: () => PermissionService,
|
|
42
34
|
ROLES_KEY: () => ROLES_KEY,
|
|
43
|
-
ROLE_SUBJECT: () => ROLE_SUBJECT
|
|
44
|
-
RolesMiddleware: () => RolesMiddleware
|
|
35
|
+
ROLE_SUBJECT: () => ROLE_SUBJECT
|
|
45
36
|
});
|
|
46
37
|
module.exports = __toCommonJS(index_exports);
|
|
47
38
|
|
|
48
39
|
// src/authzpaas.module.ts
|
|
49
|
-
var
|
|
40
|
+
var import_common9 = require("@nestjs/common");
|
|
50
41
|
var import_core4 = require("@nestjs/core");
|
|
51
42
|
|
|
52
43
|
// src/services/permission.service.ts
|
|
@@ -164,15 +155,8 @@ var Public = /* @__PURE__ */ __name2(() => (0, import_common3.SetMetadata)(IS_PU
|
|
|
164
155
|
// src/const.ts
|
|
165
156
|
var ANONYMOUS_USER_ID = "anonymous_user_id";
|
|
166
157
|
var PERMISSION_API_CONFIG_TOKEN = Symbol("PERMISSION_API_CONFIG");
|
|
167
|
-
var CACHE_CONFIG_TOKEN = Symbol("CACHE_CONFIG");
|
|
168
158
|
var AUTHZPAAS_MODULE_OPTIONS = Symbol("AUTHZPAAS_MODULE_OPTIONS");
|
|
169
159
|
var ROLES_KEY = "authzpaas:roles";
|
|
170
|
-
var PERMISSIONS_KEY = "authzpaas:permissions";
|
|
171
|
-
var ENVIRONMENT_KEY = "authzpaas:environment";
|
|
172
|
-
var NEED_LOGIN_KEY2 = "authzpaas:needLogin";
|
|
173
|
-
var DEFAULT_LOGIN_PATH = "/login";
|
|
174
|
-
var MOCK_ROLES_COOKIE_KEY = "mockRoles";
|
|
175
|
-
var ENABLE_MOCK_ROLE_KEY = "__authzpaas_enableMockRole";
|
|
176
160
|
|
|
177
161
|
// src/casl/ability.factory.ts
|
|
178
162
|
var import_common5 = require("@nestjs/common");
|
|
@@ -344,16 +328,13 @@ var PermissionService = class _PermissionService {
|
|
|
344
328
|
*/
|
|
345
329
|
async fetchFromApi(requestDto) {
|
|
346
330
|
const { timeout = 5e3 } = this.apiConfig || {};
|
|
347
|
-
const { baseUrl, userId, appId,
|
|
348
|
-
const url = `${baseUrl}/
|
|
331
|
+
const { baseUrl, userId, appId, cookie, csrfToken } = requestDto;
|
|
332
|
+
const url = `${baseUrl}/spark/app/${appId}/runtime/api/v1/permissions/roles`;
|
|
349
333
|
const requestHeaders = {
|
|
350
334
|
"Content-Type": "application/json"
|
|
351
335
|
};
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
if (cookieString) {
|
|
355
|
-
requestHeaders.Cookie = cookieString;
|
|
356
|
-
}
|
|
336
|
+
if (cookie) {
|
|
337
|
+
requestHeaders.Cookie = cookie;
|
|
357
338
|
}
|
|
358
339
|
if (csrfToken) {
|
|
359
340
|
requestHeaders["X-Suda-Csrf-Token"] = csrfToken;
|
|
@@ -362,7 +343,8 @@ var PermissionService = class _PermissionService {
|
|
|
362
343
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
363
344
|
try {
|
|
364
345
|
const response = await fetch(url, {
|
|
365
|
-
method: "
|
|
346
|
+
method: "POST",
|
|
347
|
+
credentials: "include",
|
|
366
348
|
headers: requestHeaders,
|
|
367
349
|
signal: controller.signal
|
|
368
350
|
});
|
|
@@ -378,12 +360,13 @@ var PermissionService = class _PermissionService {
|
|
|
378
360
|
const data = await response.json();
|
|
379
361
|
return {
|
|
380
362
|
userId,
|
|
381
|
-
roles: data.
|
|
363
|
+
roles: data.data?.roleList || [],
|
|
382
364
|
// TODO: 基于权限点位设置能力
|
|
383
365
|
// permissions: data.permissions || [],
|
|
384
366
|
fetchedAt: /* @__PURE__ */ new Date()
|
|
385
367
|
};
|
|
386
368
|
} catch (error) {
|
|
369
|
+
console.log("error", error);
|
|
387
370
|
clearTimeout(timeoutId);
|
|
388
371
|
let err = error;
|
|
389
372
|
if (error.name === "AbortError") {
|
|
@@ -426,14 +409,22 @@ var PermissionService = class _PermissionService {
|
|
|
426
409
|
* @returns 用户权限数据
|
|
427
410
|
* @throws PermissionDeniedException 当角色不满足时
|
|
428
411
|
*/
|
|
429
|
-
async checkRoles(requirement, userContext) {
|
|
412
|
+
async checkRoles(requirement, userContext, cookie, csrfToken) {
|
|
430
413
|
const userId = userContext?.userId || ANONYMOUS_USER_ID;
|
|
414
|
+
if (!csrfToken) {
|
|
415
|
+
throw new PermissionDeniedException({
|
|
416
|
+
cause: new Error("CSRF token is required"),
|
|
417
|
+
type: PermissionDeniedType.PERMISSION_CONFIG_QUERY_FAILED,
|
|
418
|
+
message: "CSRF token is required"
|
|
419
|
+
}, import_common7.HttpStatus.BAD_REQUEST);
|
|
420
|
+
}
|
|
431
421
|
const permissionData = await this.getUserPermissions({
|
|
422
|
+
// FIXME: 使用 request 的 base url
|
|
432
423
|
baseUrl: userContext?.baseUrl || "",
|
|
433
424
|
userId,
|
|
434
425
|
appId: userContext?.appId || "",
|
|
435
|
-
|
|
436
|
-
|
|
426
|
+
csrfToken,
|
|
427
|
+
cookie
|
|
437
428
|
});
|
|
438
429
|
if (!permissionData) {
|
|
439
430
|
throw new PermissionDeniedException({
|
|
@@ -492,22 +483,20 @@ var AuthZPaasGuard = class {
|
|
|
492
483
|
async canActivate(context) {
|
|
493
484
|
const http = context.switchToHttp();
|
|
494
485
|
const request = http.getRequest();
|
|
486
|
+
const cookie = request.headers.cookie;
|
|
487
|
+
const csrfToken = request.csrfToken;
|
|
488
|
+
const baseUrl = `${request.protocol}://${request.get("host")}`;
|
|
495
489
|
const userContext = request.userContext;
|
|
490
|
+
userContext.baseUrl = baseUrl;
|
|
496
491
|
const checkRoleRequirement = this.reflector.getAllAndOverride(ROLES_KEY, [
|
|
497
492
|
context.getHandler(),
|
|
498
493
|
context.getClass()
|
|
499
494
|
]);
|
|
500
495
|
if (checkRoleRequirement) {
|
|
501
|
-
await this.
|
|
496
|
+
await this.permissionService.checkRoles(checkRoleRequirement, userContext, cookie, csrfToken);
|
|
502
497
|
}
|
|
503
498
|
return true;
|
|
504
499
|
}
|
|
505
|
-
/**
|
|
506
|
-
* 检查角色要求
|
|
507
|
-
*/
|
|
508
|
-
async checkRoleRequirement(requirement, userContext) {
|
|
509
|
-
return this.permissionService.checkRoles(requirement, userContext);
|
|
510
|
-
}
|
|
511
500
|
};
|
|
512
501
|
AuthZPaasGuard = _ts_decorate5([
|
|
513
502
|
(0, import_common8.Injectable)(),
|
|
@@ -518,8 +507,7 @@ AuthZPaasGuard = _ts_decorate5([
|
|
|
518
507
|
])
|
|
519
508
|
], AuthZPaasGuard);
|
|
520
509
|
|
|
521
|
-
// src/
|
|
522
|
-
var import_common9 = require("@nestjs/common");
|
|
510
|
+
// src/authzpaas.module.ts
|
|
523
511
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
524
512
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
525
513
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -527,114 +515,12 @@ function _ts_decorate6(decorators, target, key, desc) {
|
|
|
527
515
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
528
516
|
}
|
|
529
517
|
__name(_ts_decorate6, "_ts_decorate");
|
|
530
|
-
function _ts_metadata4(k, v) {
|
|
531
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
532
|
-
}
|
|
533
|
-
__name(_ts_metadata4, "_ts_metadata");
|
|
534
|
-
var RolesMiddleware = class _RolesMiddleware {
|
|
535
|
-
static {
|
|
536
|
-
__name(this, "RolesMiddleware");
|
|
537
|
-
}
|
|
538
|
-
permissionService;
|
|
539
|
-
logger = new import_common9.Logger(_RolesMiddleware.name);
|
|
540
|
-
constructor(permissionService) {
|
|
541
|
-
this.permissionService = permissionService;
|
|
542
|
-
}
|
|
543
|
-
async use(req, _res, next) {
|
|
544
|
-
try {
|
|
545
|
-
const baseUrl = `${req.protocol}://${req.get("host")}`;
|
|
546
|
-
const userId = req.userContext?.userId ?? "";
|
|
547
|
-
const appId = req.userContext?.appId ?? "";
|
|
548
|
-
const cookies = req.cookies ?? {};
|
|
549
|
-
const csrfToken = req.headers["x-suda-csrf-token"] ?? "";
|
|
550
|
-
this.logger.debug(`Fetching roles for user: ${userId}`);
|
|
551
|
-
const permissionData = await this.permissionService.getUserPermissions({
|
|
552
|
-
baseUrl,
|
|
553
|
-
userId,
|
|
554
|
-
appId,
|
|
555
|
-
cookies,
|
|
556
|
-
csrfToken
|
|
557
|
-
});
|
|
558
|
-
let roles;
|
|
559
|
-
if (permissionData) {
|
|
560
|
-
roles = permissionData.roles;
|
|
561
|
-
}
|
|
562
|
-
req.userContext.baseUrl = baseUrl;
|
|
563
|
-
req.userContext.userRoles = roles;
|
|
564
|
-
req.userContext.userId = userId;
|
|
565
|
-
req.userContext.cookies = cookies;
|
|
566
|
-
req.userContext.csrfToken = csrfToken;
|
|
567
|
-
this.logger.debug(`User ${userId} roles loaded: [${roles?.join(", ")}]`);
|
|
568
|
-
next();
|
|
569
|
-
} catch (error) {
|
|
570
|
-
this.logger.warn(`Failed to fetch roles for request: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
571
|
-
next();
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
RolesMiddleware = _ts_decorate6([
|
|
576
|
-
(0, import_common9.Injectable)(),
|
|
577
|
-
_ts_metadata4("design:type", Function),
|
|
578
|
-
_ts_metadata4("design:paramtypes", [
|
|
579
|
-
typeof PermissionService === "undefined" ? Object : PermissionService
|
|
580
|
-
])
|
|
581
|
-
], RolesMiddleware);
|
|
582
|
-
|
|
583
|
-
// src/filters/authzpaas-exception.filter.ts
|
|
584
|
-
var import_common10 = require("@nestjs/common");
|
|
585
|
-
function _ts_decorate7(decorators, target, key, desc) {
|
|
586
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
587
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
588
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
589
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
590
|
-
}
|
|
591
|
-
__name(_ts_decorate7, "_ts_decorate");
|
|
592
|
-
var AuthZPaasExceptionFilter = class {
|
|
593
|
-
static {
|
|
594
|
-
__name(this, "AuthZPaasExceptionFilter");
|
|
595
|
-
}
|
|
596
|
-
catch(exception, host) {
|
|
597
|
-
const ctx = host.switchToHttp();
|
|
598
|
-
const response = ctx.getResponse();
|
|
599
|
-
const status = exception.getStatus();
|
|
600
|
-
const exceptionResponse = exception.getResponse();
|
|
601
|
-
const errorResponse = {
|
|
602
|
-
statusCode: status,
|
|
603
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
604
|
-
cause: exception.cause,
|
|
605
|
-
type: exception.type,
|
|
606
|
-
message: typeof exceptionResponse === "string" ? exceptionResponse : exceptionResponse.message || "\u6743\u9650\u4E0D\u8DB3"
|
|
607
|
-
};
|
|
608
|
-
if (exception.details.requiredRoles) {
|
|
609
|
-
errorResponse.requiredRoles = exception.details.requiredRoles;
|
|
610
|
-
}
|
|
611
|
-
if (exception.details.requiredPermissions) {
|
|
612
|
-
errorResponse.requiredPermissions = exception.details.requiredPermissions;
|
|
613
|
-
}
|
|
614
|
-
if (exception.details.metadata) {
|
|
615
|
-
errorResponse.metadata = exception.details.metadata;
|
|
616
|
-
}
|
|
617
|
-
response.status(status).json(errorResponse);
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
AuthZPaasExceptionFilter = _ts_decorate7([
|
|
621
|
-
(0, import_common10.Catch)(PermissionDeniedException)
|
|
622
|
-
], AuthZPaasExceptionFilter);
|
|
623
|
-
|
|
624
|
-
// src/authzpaas.module.ts
|
|
625
|
-
function _ts_decorate8(decorators, target, key, desc) {
|
|
626
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
627
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
628
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
629
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
630
|
-
}
|
|
631
|
-
__name(_ts_decorate8, "_ts_decorate");
|
|
632
518
|
var AuthZPaasModule = class _AuthZPaasModule {
|
|
633
519
|
static {
|
|
634
520
|
__name(this, "AuthZPaasModule");
|
|
635
521
|
}
|
|
636
522
|
static forRoot(options) {
|
|
637
|
-
const { permissionApi } = options;
|
|
523
|
+
const { permissionApi = {} } = options || {};
|
|
638
524
|
return {
|
|
639
525
|
module: _AuthZPaasModule,
|
|
640
526
|
global: true,
|
|
@@ -657,21 +543,15 @@ var AuthZPaasModule = class _AuthZPaasModule {
|
|
|
657
543
|
PermissionService,
|
|
658
544
|
AbilityFactory,
|
|
659
545
|
AuthZPaasGuard,
|
|
660
|
-
RolesMiddleware,
|
|
661
546
|
// 守卫提供者
|
|
662
547
|
{
|
|
663
548
|
provide: import_core4.APP_GUARD,
|
|
664
549
|
useClass: AuthZPaasGuard
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
provide: import_core4.APP_FILTER,
|
|
668
|
-
useClass: AuthZPaasExceptionFilter
|
|
669
550
|
}
|
|
670
551
|
],
|
|
671
552
|
exports: [
|
|
672
553
|
PermissionService,
|
|
673
|
-
AbilityFactory
|
|
674
|
-
RolesMiddleware
|
|
554
|
+
AbilityFactory
|
|
675
555
|
]
|
|
676
556
|
};
|
|
677
557
|
}
|
|
@@ -735,31 +615,25 @@ var AuthZPaasModule = class _AuthZPaasModule {
|
|
|
735
615
|
PermissionService,
|
|
736
616
|
AbilityFactory,
|
|
737
617
|
AuthZPaasGuard,
|
|
738
|
-
RolesMiddleware,
|
|
739
618
|
// 守卫提供者
|
|
740
619
|
{
|
|
741
620
|
provide: import_core4.APP_GUARD,
|
|
742
621
|
useClass: AuthZPaasGuard
|
|
743
|
-
},
|
|
744
|
-
{
|
|
745
|
-
provide: import_core4.APP_FILTER,
|
|
746
|
-
useClass: AuthZPaasExceptionFilter
|
|
747
622
|
}
|
|
748
623
|
],
|
|
749
624
|
exports: [
|
|
750
625
|
PermissionService,
|
|
751
|
-
AbilityFactory
|
|
752
|
-
RolesMiddleware
|
|
626
|
+
AbilityFactory
|
|
753
627
|
]
|
|
754
628
|
};
|
|
755
629
|
}
|
|
756
630
|
};
|
|
757
|
-
AuthZPaasModule =
|
|
758
|
-
(0,
|
|
631
|
+
AuthZPaasModule = _ts_decorate6([
|
|
632
|
+
(0, import_common9.Module)({})
|
|
759
633
|
], AuthZPaasModule);
|
|
760
634
|
|
|
761
635
|
// src/decorators/can-role.decorator.ts
|
|
762
|
-
var
|
|
636
|
+
var import_common10 = require("@nestjs/common");
|
|
763
637
|
var CanRole = /* @__PURE__ */ __name((role, and = false) => {
|
|
764
638
|
let requirement;
|
|
765
639
|
if (!Array.isArray(role) && typeof role === "string") {
|
|
@@ -777,30 +651,21 @@ var CanRole = /* @__PURE__ */ __name((role, and = false) => {
|
|
|
777
651
|
} else {
|
|
778
652
|
throw new Error("Invalid CanRole parameter: " + JSON.stringify(role));
|
|
779
653
|
}
|
|
780
|
-
return (0,
|
|
654
|
+
return (0, import_common10.SetMetadata)(ROLES_KEY, requirement);
|
|
781
655
|
}, "CanRole");
|
|
782
656
|
// Annotate the CommonJS export names for ESM import in node:
|
|
783
657
|
0 && (module.exports = {
|
|
784
658
|
ANONYMOUS_USER_ID,
|
|
785
659
|
AUTHZPAAS_MODULE_OPTIONS,
|
|
786
660
|
AbilityFactory,
|
|
787
|
-
AuthZPaasExceptionFilter,
|
|
788
661
|
AuthZPaasGuard,
|
|
789
662
|
AuthZPaasModule,
|
|
790
|
-
CACHE_CONFIG_TOKEN,
|
|
791
663
|
CanRole,
|
|
792
|
-
DEFAULT_LOGIN_PATH,
|
|
793
|
-
ENABLE_MOCK_ROLE_KEY,
|
|
794
|
-
ENVIRONMENT_KEY,
|
|
795
|
-
MOCK_ROLES_COOKIE_KEY,
|
|
796
|
-
NEED_LOGIN_KEY,
|
|
797
|
-
PERMISSIONS_KEY,
|
|
798
664
|
PERMISSION_API_CONFIG_TOKEN,
|
|
799
665
|
PermissionDeniedException,
|
|
800
666
|
PermissionDeniedType,
|
|
801
667
|
PermissionService,
|
|
802
668
|
ROLES_KEY,
|
|
803
|
-
ROLE_SUBJECT
|
|
804
|
-
RolesMiddleware
|
|
669
|
+
ROLE_SUBJECT
|
|
805
670
|
});
|
|
806
671
|
//# sourceMappingURL=index.cjs.map
|