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