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