sumor 3.0.2 → 3.0.4

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 CHANGED
@@ -220,12 +220,157 @@ await req.sumor.revokeSession(sessionId)
220
220
 
221
221
  Sumor automatically registers these routes:
222
222
 
223
- - `GET /api/oauth/info` - Get OAuth provider info and authorization URL (no auth required)
224
223
  - `GET /api/oauth/callback` - Handle OAuth provider callback with authorization code (no auth required)
225
- - `PUT /api/oauth/token` - Refresh access token (can use refreshToken from body or cookie)
224
+ - `PUT /api/oauth/token` - Refresh access token and get user info + authorization URL (can use refreshToken from body or cookie)
225
+ - Response includes `endpoint` and `authorizeUrl` for OAuth configuration, and `user` object with current user info
226
226
  - `POST /api/oauth/logout` - Logout and revoke session (requires valid token)
227
227
 
228
- ## 🔧 Configuration
228
+ ## 🎯 Web Client (Sumor Class)
229
+
230
+ The Sumor framework includes a client-side class for browser applications to manage OAuth and user state.
231
+
232
+ ### Basic Setup
233
+
234
+ ```typescript
235
+ import { setupSumor } from 'sumor'
236
+
237
+ // Call this on app initialization
238
+ await setupSumor()
239
+
240
+ // Now use window.sumor to access the Sumor client
241
+ console.log(window.sumor.user) // Current user info or null
242
+ ```
243
+
244
+ ### Sumor Client Properties
245
+
246
+ - `endpoint` - OAuth provider endpoint
247
+ - `authorizeUrl` - Authorization URL for login redirect
248
+ - `user` - Current user object or null
249
+ - `id` - User ID
250
+ - `isVerified` - Verification status
251
+ - `roles` - Comma-separated role list
252
+ - `permissions` - Comma-separated permission list
253
+
254
+ ### Sumor Client Methods
255
+
256
+ #### refresh(force = false)
257
+
258
+ Refresh OAuth configuration and user info from `PUT /api/oauth/token` using the stored refresh token.
259
+
260
+ ```typescript
261
+ // Use cache if available
262
+ await window.sumor.refresh()
263
+
264
+ // Force refresh, ignore cache
265
+ await window.sumor.refresh(true)
266
+ ```
267
+
268
+ #### refreshConfig()
269
+
270
+ Manually refresh configuration (same as `refresh(true)`).
271
+
272
+ ```typescript
273
+ await window.sumor.refreshConfig()
274
+ ```
275
+
276
+ #### login()
277
+
278
+ Redirect to OAuth authorization page.
279
+
280
+ ```typescript
281
+ window.sumor.login()
282
+ ```
283
+
284
+ #### logout()
285
+
286
+ Logout and clear local user state.
287
+
288
+ ```typescript
289
+ await window.sumor.logout()
290
+ // window.sumor.user becomes null
291
+ ```
292
+
293
+ #### hasPermission(module, operation = '\*')
294
+
295
+ Check if user has a specific permission.
296
+
297
+ ```typescript
298
+ // Check specific permission
299
+ if (window.sumor.hasPermission('posts', 'edit')) {
300
+ // User can edit posts
301
+ }
302
+
303
+ // Check module (any operation)
304
+ if (window.sumor.hasPermission('posts')) {
305
+ // User has any posts permission
306
+ }
307
+
308
+ if (window.sumor.hasPermission('posts', '*')) {
309
+ // Same as above
310
+ }
311
+ ```
312
+
313
+ #### hasRole(role)
314
+
315
+ Check if user has a specific role.
316
+
317
+ ```typescript
318
+ if (window.sumor.hasRole('admin')) {
319
+ // User is admin
320
+ }
321
+ ```
322
+
323
+ #### onUserChange(callback)
324
+
325
+ Subscribe to user state changes (login, logout, token refresh).
326
+
327
+ ```typescript
328
+ window.sumor.onUserChange(user => {
329
+ if (user) {
330
+ console.log('User logged in:', user.id)
331
+ } else {
332
+ console.log('User logged out')
333
+ }
334
+ })
335
+ ```
336
+
337
+ ### Web Client Example
338
+
339
+ ```typescript
340
+ import { setupSumor } from 'sumor'
341
+ import { ref, watch } from 'vue'
342
+
343
+ export default {
344
+ setup() {
345
+ const userInfo = ref(null)
346
+ const isLoggedIn = ref(false)
347
+
348
+ onMounted(async () => {
349
+ await setupSumor()
350
+
351
+ // Get initial user state
352
+ userInfo.value = window.sumor.user
353
+ isLoggedIn.value = !!window.sumor.user
354
+
355
+ // Subscribe to user changes
356
+ window.sumor.onUserChange(user => {
357
+ userInfo.value = user
358
+ isLoggedIn.value = !!user
359
+ })
360
+ })
361
+
362
+ return {
363
+ userInfo,
364
+ isLoggedIn,
365
+ login: () => window.sumor.login(),
366
+ logout: () => window.sumor.logout(),
367
+ canEdit: () => window.sumor.hasPermission('posts', 'edit')
368
+ }
369
+ }
370
+ }
371
+ ```
372
+
373
+ ## 📚 API Reference
229
374
 
230
375
  Sumor uses environment variables for configuration. The key is configuring the OAuth provider endpoint:
231
376
 
@@ -266,6 +411,7 @@ OAUTH_REDIRECT_URI=https://app.mycompany.com/api/oauth/callback
266
411
  ### Example 1: Protect Routes with Permission Checks
267
412
 
268
413
  ```typescript
414
+ // Server-side: Express route with permission check
269
415
  app.post('/api/posts', (req: any, res) => {
270
416
  // Check if user has permission
271
417
  const permissions = req.jwtUser.permissions?.split(',') || []
@@ -277,6 +423,18 @@ app.post('/api/posts', (req: any, res) => {
277
423
  // Create post logic here
278
424
  res.json({ postId: 123 })
279
425
  })
426
+
427
+ // Client-side: Vue component with permission check
428
+ export default {
429
+ setup() {
430
+ return {
431
+ canCreatePost: () => window.sumor.hasPermission('posts', 'create')
432
+ }
433
+ }
434
+ }
435
+
436
+ // Template
437
+ <button v-if="canCreatePost()" @click="createPost">Create Post</button>
280
438
  ```
281
439
 
282
440
  ### Example 2: Multi-Tenant Support
@@ -418,7 +576,7 @@ const permissions = req.jwtUser.permissions?.split(',').map(p => p.trim()) || []
418
576
  ┌──────────────────────────────────────┐
419
577
  │ Your Express App (Port 3000) │
420
578
  │ ┌────────────────────────────────┐ │
421
- │ │ GET /api/oauth/info │ │ (2) Get OAuth URL
579
+ │ │ PUT /api/oauth/token │ │ (2) Get OAuth URL & User Info
422
580
  │ │ GET /api/oauth/callback │ │
423
581
  │ │ POST /api/oauth/logout │ │
424
582
  │ └────────────────────────────────┘ │
@@ -441,7 +599,7 @@ const permissions = req.jwtUser.permissions?.split(',').map(p => p.trim()) || []
441
599
  **Flow Steps:**
442
600
 
443
601
  1. User clicks "Login" on your app
444
- 2. App calls `GET /api/oauth/info` to get OAuth provider URL
602
+ 2. App calls `PUT /api/oauth/token` with refresh token to get OAuth provider URL and user info
445
603
  3. User redirected to OAuth provider
446
604
  4. OAuth provider authenticates and redirects back to `/api/oauth/callback` with authorization code
447
605
  5. Server exchanges code for JWT token via ITS OAuth API
@@ -2,7 +2,7 @@
2
2
  * Token 刷新控制器
3
3
  * PUT /api/oauth/token
4
4
  *
5
- * 刷新过期的 access_token
5
+ * 刷新过期的 access_token,并返回用户信息
6
6
  */
7
7
  import { Request, Response } from 'express';
8
8
  export default function tokenRefreshController(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"tokenRefreshController.d.ts","sourceRoot":"","sources":["../../../server/controllers/tokenRefreshController.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAI3C,wBAA8B,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,+CAgD/E"}
1
+ {"version":3,"file":"tokenRefreshController.d.ts","sourceRoot":"","sources":["../../../server/controllers/tokenRefreshController.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAO3C,wBAA8B,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,+CAyE/E"}
@@ -3,7 +3,7 @@
3
3
  * Token 刷新控制器
4
4
  * PUT /api/oauth/token
5
5
  *
6
- * 刷新过期的 access_token
6
+ * 刷新过期的 access_token,并返回用户信息
7
7
  */
8
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
9
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -12,6 +12,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.default = tokenRefreshController;
13
13
  const oauthService_1 = __importDefault(require("../services/oauthService"));
14
14
  const oauthTokenUtils_1 = require("../utils/oauthTokenUtils");
15
+ const tokenModel_1 = require("../models/tokenModel");
16
+ const config_1 = require("../utils/config");
17
+ const authorizationUrlGenerator_1 = require("../utils/authorizationUrlGenerator");
15
18
  async function tokenRefreshController(req, res) {
16
19
  try {
17
20
  // 仅支持驼峰格式(refreshToken)
@@ -38,12 +41,36 @@ async function tokenRefreshController(req, res) {
38
41
  if (tokenData.refreshToken && tokenData.refreshToken !== refreshToken) {
39
42
  (0, oauthTokenUtils_1.setOAuthTokenCookie)(res, tokenData.refreshToken, 2592000, 'refresh'); // 30 days
40
43
  }
41
- // 安全做法:只返回 code 和 message
42
- // Token 已通过 HttpOnly Cookie 设置,无需在响应体中返回
43
- // 防止 token 泄露风险
44
+ // 验证新的 accessToken 获取用户信息
45
+ let user = null;
46
+ try {
47
+ const tokenModel = (0, tokenModel_1.getTokenModel)();
48
+ const claims = await tokenModel.verify(tokenData.accessToken);
49
+ if (claims.sub) {
50
+ user = {
51
+ id: claims.sub,
52
+ isVerified: claims.isVerified || 0,
53
+ roles: claims.roles || '',
54
+ permissions: claims.permissions || ''
55
+ };
56
+ }
57
+ }
58
+ catch (error) {
59
+ // Token 验证失败,返回 null user
60
+ console.error('Failed to verify new token:', error);
61
+ }
62
+ // ✅ 返回用户信息供客户端使用
63
+ // Token 已通过 HttpOnly Cookie 设置,响应中包含 user 信息用于更新客户端状态
64
+ const config = (0, config_1.getOAuthConfig)();
65
+ const oauthAuthorizeUrl = (0, authorizationUrlGenerator_1.generateAuthorizationUrl)();
44
66
  res.status(200).json({
45
67
  code: 'OK',
46
- message: 'Token 刷新成功'
68
+ message: 'Token 刷新成功',
69
+ data: {
70
+ endpoint: config.endpoint,
71
+ authorizeUrl: oauthAuthorizeUrl,
72
+ user
73
+ }
47
74
  });
48
75
  }
49
76
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"tokenRefreshController.js","sourceRoot":"","sources":["../../../server/controllers/tokenRefreshController.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;AAMH,yCAgDC;AAnDD,4EAAmD;AACnD,8DAA8D;AAE/C,KAAK,UAAU,sBAAsB,CAAC,GAAY,EAAE,GAAa;IAC9E,IAAI,CAAC;QACH,wBAAwB;QACxB,6BAA6B;QAC7B,IAAI,YAAY,GAAG,GAAG,CAAC,IAAI,CAAC,YAAY,CAAA;QAExC,wBAAwB;QACxB,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,YAAY,GAAG,GAAG,CAAC,OAAO,EAAE,aAAa,CAAA;QAC3C,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,oBAAoB;aAC9B,CAAC,CAAA;QACJ,CAAC;QAED,6BAA6B;QAC7B,MAAM,YAAY,GAAG,IAAI,sBAAY,EAAE,CAAA;QACvC,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAA;QAErE,mBAAmB;QACnB,mBAAmB;QACnB,IAAA,qCAAmB,EAAC,GAAG,EAAE,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAE9E,4BAA4B;QAC5B,4CAA4C;QAC5C,IAAI,SAAS,CAAC,YAAY,IAAI,SAAS,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;YACtE,IAAA,qCAAmB,EAAC,GAAG,EAAE,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA,CAAC,UAAU;QACjF,CAAC;QAED,4BAA4B;QAC5B,yCAAyC;QACzC,gBAAgB;QAChB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,YAAY;SACtB,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,CAAA;QAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,IAAI,YAAY,CAAA;QAElD,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;SACtB,CAAC,CAAA;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"tokenRefreshController.js","sourceRoot":"","sources":["../../../server/controllers/tokenRefreshController.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,8 @@ import { Response, NextFunction } from 'express';
14
14
  * - jti: JWT 唯一标识
15
15
  * - roleLevel: 用户角色级别
16
16
  * - isVerified: 用户认证状态标记(0=未认证, 1=已认证)
17
+ * - roles: 用户角色列表(逗号分隔的字符串)
18
+ * - permissions: 用户权限列表(逗号分隔的2段式权限字符串)
17
19
  * - iss: 签发者
18
20
  * - sub: 用户 ID(标准 JWT 字段)
19
21
  * - aud: 受众
@@ -1 +1 @@
1
- {"version":3,"file":"loadJwtUserMiddleware.d.ts","sourceRoot":"","sources":["../../../server/middlewares/loadJwtUserMiddleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAIhD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED,eAAe,qBAAqB,CAAA"}
1
+ {"version":3,"file":"loadJwtUserMiddleware.d.ts","sourceRoot":"","sources":["../../../server/middlewares/loadJwtUserMiddleware.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAIhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED,eAAe,qBAAqB,CAAA"}
@@ -18,6 +18,8 @@ const authUtils_1 = require("../utils/authUtils");
18
18
  * - jti: JWT 唯一标识
19
19
  * - roleLevel: 用户角色级别
20
20
  * - isVerified: 用户认证状态标记(0=未认证, 1=已认证)
21
+ * - roles: 用户角色列表(逗号分隔的字符串)
22
+ * - permissions: 用户权限列表(逗号分隔的2段式权限字符串)
21
23
  * - iss: 签发者
22
24
  * - sub: 用户 ID(标准 JWT 字段)
23
25
  * - aud: 受众
@@ -1 +1 @@
1
- {"version":3,"file":"loadJwtUserMiddleware.js","sourceRoot":"","sources":["../../../server/middlewares/loadJwtUserMiddleware.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAuBH,sDAyCC;AA7DD,qDAAkD;AAClD,kDAAmD;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,qBAAqB,CACzC,GAAQ,EACR,GAAa,EACb,IAAkB;IAElB,IAAI,CAAC;QACH,qBAAqB;QACrB,MAAM,KAAK,GAAG,IAAA,0BAAc,EAAC,GAAG,CAAC,CAAA;QAEjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;YAClB,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAED,cAAc;QACd,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAW,EAAC,KAAK,CAAC,CAAA;YAEvC,mBAAmB;YACnB,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAChB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;gBAClB,OAAO,IAAI,EAAE,CAAA;YACf,CAAC;YAED,oBAAoB;YACpB,GAAG,CAAC,OAAO,GAAG;gBACZ,GAAG,MAAM;gBACT,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,sBAAsB;gBAC1C,GAAG,EAAE,MAAM,CAAC,GAAG;aAChB,CAAA;YAED,IAAI,EAAE,CAAA;QACR,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,wBAAwB;YACxB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;YAClB,IAAI,EAAE,CAAA;QACR,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,KAAK,CAAC,CAAA;IACb,CAAC;AACH,CAAC;AAED,kBAAe,qBAAqB,CAAA"}
1
+ {"version":3,"file":"loadJwtUserMiddleware.js","sourceRoot":"","sources":["../../../server/middlewares/loadJwtUserMiddleware.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAyBH,sDAyCC;AA/DD,qDAAkD;AAClD,kDAAmD;AAEnD;;;;;;;;;;;;;;;;;;GAkBG;AACI,KAAK,UAAU,qBAAqB,CACzC,GAAQ,EACR,GAAa,EACb,IAAkB;IAElB,IAAI,CAAC;QACH,qBAAqB;QACrB,MAAM,KAAK,GAAG,IAAA,0BAAc,EAAC,GAAG,CAAC,CAAA;QAEjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;YAClB,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAED,cAAc;QACd,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAA,wBAAW,EAAC,KAAK,CAAC,CAAA;YAEvC,mBAAmB;YACnB,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAChB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;gBAClB,OAAO,IAAI,EAAE,CAAA;YACf,CAAC;YAED,oBAAoB;YACpB,GAAG,CAAC,OAAO,GAAG;gBACZ,GAAG,MAAM;gBACT,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,sBAAsB;gBAC1C,GAAG,EAAE,MAAM,CAAC,GAAG;aAChB,CAAA;YAED,IAAI,EAAE,CAAA;QACR,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,wBAAwB;YACxB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;YAClB,IAAI,EAAE,CAAA;QACR,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,KAAK,CAAC,CAAA;IACb,CAAC;AACH,CAAC;AAED,kBAAe,qBAAqB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,QAAA,MAAM,SAAS,4CAAmB,CAAA;AAyClC,eAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,QAAA,MAAM,SAAS,4CAAmB,CAAA;AA+BlC,eAAe,SAAS,CAAA"}
@@ -10,7 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
10
10
  const express_1 = __importDefault(require("express"));
11
11
  const tokenRefreshController_1 = __importDefault(require("./controllers/tokenRefreshController"));
12
12
  const oauthCallbackController_1 = __importDefault(require("./controllers/oauthCallbackController"));
13
- const infoController_1 = require("./controllers/infoController");
14
13
  const logoutController_1 = require("./controllers/logoutController");
15
14
  const itsRoutes = express_1.default.Router();
16
15
  /**
@@ -33,15 +32,6 @@ itsRoutes.put('/token', tokenRefreshController_1.default);
33
32
  * 无需认证 - ITS 直接调用此端点
34
33
  */
35
34
  itsRoutes.get('/callback', oauthCallbackController_1.default);
36
- /**
37
- * 获取 ITS 配置信息 - 无需认证
38
- * GET /api/oauth/info
39
- *
40
- * 返回:
41
- * - endpoint: ITS 服务器地址
42
- * - oauthAuthorizeUrl: OAuth 授权 URL
43
- */
44
- itsRoutes.get('/info', infoController_1.getItsInfo);
45
35
  /**
46
36
  * 用户登出 - 需要有效的 Token
47
37
  * POST /api/oauth/logout
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAEH,sDAA6B;AAC7B,kGAAyE;AACzE,oGAA2E;AAC3E,iEAAyD;AACzD,qEAAuD;AAEvD,MAAM,SAAS,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;AAElC;;GAEG;AAEH;;;;;;;GAOG;AACH,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,gCAAsB,CAAC,CAAA;AAE/C;;;;;;GAMG;AACH,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,iCAAuB,CAAC,CAAA;AAEnD;;;;;;;GAOG;AACH,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,2BAAU,CAAC,CAAA;AAElC;;;GAGG;AACH,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,yBAAM,CAAC,CAAA;AAEjC,kBAAe,SAAS,CAAA"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAEH,sDAA6B;AAC7B,kGAAyE;AACzE,oGAA2E;AAC3E,qEAAuD;AAEvD,MAAM,SAAS,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;AAElC;;GAEG;AAEH;;;;;;;GAOG;AACH,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,gCAAsB,CAAC,CAAA;AAE/C;;;;;;GAMG;AACH,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,iCAAuB,CAAC,CAAA;AAEnD;;;GAGG;AACH,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,yBAAM,CAAC,CAAA;AAEjC,kBAAe,SAAS,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 生成授权 URL 工具函数
3
+ * RFC 6749 §4.1.1,支持 PKCE(RFC 7636)用于增强安全性
4
+ */
5
+ /**
6
+ * 生成授权 URL
7
+ * RFC 6749 §4.1.1,支持 PKCE(RFC 7636)用于增强安全性
8
+ */
9
+ export declare function generateAuthorizationUrl(): string;
10
+ //# sourceMappingURL=authorizationUrlGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorizationUrlGenerator.d.ts","sourceRoot":"","sources":["../../../server/utils/authorizationUrlGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkCH;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA0BjD"}
@@ -1,15 +1,15 @@
1
1
  "use strict";
2
2
  /**
3
- * OAuth 信息控制器
4
- * 获取 ITS 端点信息
3
+ * 生成授权 URL 工具函数
4
+ * RFC 6749 §4.1.1,支持 PKCE(RFC 7636)用于增强安全性
5
5
  */
6
6
  var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
8
  };
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.getItsInfo = void 0;
10
+ exports.generateAuthorizationUrl = generateAuthorizationUrl;
11
11
  const crypto_1 = __importDefault(require("crypto"));
12
- const config_1 = require("../utils/config");
12
+ const config_1 = require("./config");
13
13
  /**
14
14
  * 生成 PKCE code_challenge 和 code_verifier
15
15
  */
@@ -58,26 +58,4 @@ function generateAuthorizationUrl() {
58
58
  const authUrl = `${oauthConfig.baseUrl}/authorize?${params.toString()}`;
59
59
  return authUrl;
60
60
  }
61
- /**
62
- * 获取 ITS 配置信息
63
- * GET /api/oauth/info
64
- *
65
- * 无需认证 - 在 JWT 中间件之前调用
66
- */
67
- const getItsInfo = async (req, res, next) => {
68
- try {
69
- const oauthAuthorizeUrl = generateAuthorizationUrl();
70
- res.json({
71
- code: 'OK',
72
- data: {
73
- endpoint: req.config.its?.endpoint,
74
- authorizeUrl: oauthAuthorizeUrl
75
- }
76
- });
77
- }
78
- catch (error) {
79
- next(error);
80
- }
81
- };
82
- exports.getItsInfo = getItsInfo;
83
- //# sourceMappingURL=infoController.js.map
61
+ //# sourceMappingURL=authorizationUrlGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorizationUrlGenerator.js","sourceRoot":"","sources":["../../../server/utils/authorizationUrlGenerator.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAsCH,4DA0BC;AA9DD,oDAA2B;AAC3B,qCAAyC;AAEzC;;GAEG;AACH,SAAS,qBAAqB;IAI5B,MAAM,YAAY,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3D,MAAM,SAAS,GAAG,gBAAM;SACrB,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,YAAY,CAAC;SACpB,MAAM,CAAC,QAAQ,CAAC;SAChB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IAEpB,OAAO;QACL,aAAa,EAAE,SAAS;QACxB,YAAY,EAAE,YAAY;KAC3B,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa;IACpB,OAAO,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAgB,wBAAwB;IACtC,MAAM,WAAW,GAAG,IAAA,uBAAc,GAAE,CAAA;IACpC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,qBAAqB,EAAE,CAAA;IAE/D,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,CAAA;IAEnC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAClD,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,EAAE,CAAA;IACnC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,WAAW,CAAA;IAEvF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,WAAW,EAAE,GAAG;QAChB,YAAY,EAAE,MAAM;QACpB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,cAAc;QACrB,aAAa,EAAE,aAAa;QAC5B,mBAAmB,EAAE,MAAM;KAC5B,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,GAAG,WAAW,CAAC,OAAO,cAAc,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAA;IAEvE,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -10,18 +10,39 @@ export declare class ApiError extends Error {
10
10
  status?: number;
11
11
  constructor(message: string, code: string | number, status?: number);
12
12
  }
13
+ export interface UserInfo {
14
+ id: string;
15
+ isVerified: number;
16
+ roles: string;
17
+ permissions: string;
18
+ }
19
+ /**
20
+ * 用户变化回调类型
21
+ */
22
+ export type UserChangeCallback = (user: UserInfo | null) => void;
13
23
  export declare class Sumor {
14
24
  endpoint: string;
15
25
  authorizeUrl: string;
26
+ user: UserInfo | null;
16
27
  axios: AxiosInstance;
17
28
  private loaded;
18
29
  private loadTime;
19
30
  private readonly CACHE_TTL;
20
31
  private isRefreshing;
21
32
  private refreshSubscribers;
33
+ private userChangeSubscribers;
22
34
  constructor();
23
35
  private subscribeTokenRefresh;
24
36
  private onTokenRefreshed;
37
+ /**
38
+ * 订阅用户变化事件
39
+ * @param callback 用户变化时的回调函数
40
+ */
41
+ onUserChange(callback: UserChangeCallback): void;
42
+ /**
43
+ * 触发用户变化事件
44
+ */
45
+ private emitUserChange;
25
46
  /**
26
47
  * 创建 Axios 实例并配置拦截器
27
48
  */
@@ -39,7 +60,12 @@ export declare class Sumor {
39
60
  */
40
61
  post<T = any>(url: string, data: Record<string, any>, config?: AxiosRequestConfig): Promise<T>;
41
62
  private isCacheValid;
42
- init(): Promise<void>;
63
+ /**
64
+ * 刷新 OAuth 信息和用户状态
65
+ * 通过刷新 access token 接口获取 endpoint、authorizeUrl 和用户信息
66
+ * @param force 是否强制刷新,忽略缓存
67
+ */
68
+ refreshToken(force?: boolean): Promise<void>;
43
69
  getAvatarUrl(id: string): string;
44
70
  getHomeUrl(): string;
45
71
  getSiteUrl(): string;
@@ -57,5 +83,22 @@ export declare class Sumor {
57
83
  * 手动刷新配置(用于处理长期运行的应用需要更新配置的情况)
58
84
  */
59
85
  refreshConfig(): Promise<void>;
86
+ /**
87
+ * 检查用户是否有特定权限
88
+ * @param module 模块名称(如:posts、comments)
89
+ * @param operation 操作名称(如:view、edit、delete),为 * 或不传时表示检查模块的任何权限
90
+ * @returns 是否拥有权限
91
+ *
92
+ * 例如:
93
+ * - hasPermission('posts', 'edit') 检查是否有 'posts:edit' 权限
94
+ * - hasPermission('posts', '*') 或 hasPermission('posts') 检查是否有任何 posts 权限
95
+ */
96
+ hasPermission(module: string, operation?: string): boolean;
97
+ /**
98
+ * 检查用户是否拥有指定角色
99
+ * @param role 角色名称
100
+ * @returns 是否拥有该角色
101
+ */
102
+ hasRole(role: string): boolean;
60
103
  }
61
104
  //# sourceMappingURL=Sumor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sumor.d.ts","sourceRoot":"","sources":["../../web/Sumor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAc,EAAE,aAAa,EAAE,kBAAkB,EAAc,MAAM,OAAO,CAAA;AAW5E;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAMpE;AAED,qBAAa,KAAK;IACT,QAAQ,EAAE,MAAM,CAAK;IACrB,YAAY,EAAE,MAAM,CAAK;IACzB,KAAK,EAAE,aAAa,CAAA;IAC3B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,kBAAkB,CAAwB;;IAOlD,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,gBAAgB;IAKxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkG3B;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,GAAG,EACnB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAChC,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAQb;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,GAAG,EACf,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAIb;;OAEG;IACG,IAAI,CAAC,CAAC,GAAG,GAAG,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAIb,OAAO,CAAC,YAAY;IAQd,IAAI;IAoBV,YAAY,CAAC,EAAE,EAAE,MAAM;IAIvB,UAAU;IAIV,UAAU;IAIV,UAAU;IAIV,cAAc;IAId;;OAEG;IACH,KAAK;IAQL;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B;;OAEG;IACG,aAAa;CAKpB"}
1
+ {"version":3,"file":"Sumor.d.ts","sourceRoot":"","sources":["../../web/Sumor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAc,EAAE,aAAa,EAAE,kBAAkB,EAAc,MAAM,OAAO,CAAA;AAW5E;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;gBAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAMpE;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAWD;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAA;AAEhE,qBAAa,KAAK;IACT,QAAQ,EAAE,MAAM,CAAK;IACrB,YAAY,EAAE,MAAM,CAAK;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAO;IAC5B,KAAK,EAAE,aAAa,CAAA;IAC3B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,kBAAkB,CAAwB;IAClD,OAAO,CAAC,qBAAqB,CAAgC;;IAO7D,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,gBAAgB;IAKxB;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAIhD;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgH3B;;OAEG;IACG,OAAO,CAAC,CAAC,GAAG,GAAG,EACnB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAChC,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAQb;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,GAAG,EACf,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAIb;;OAEG;IACG,IAAI,CAAC,CAAC,GAAG,GAAG,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,CAAC;IAIb,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;IACG,YAAY,CAAC,KAAK,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CzD,YAAY,CAAC,EAAE,EAAE,MAAM;IAIvB,UAAU;IAIV,UAAU;IAIV,UAAU;IAIV,cAAc;IAId;;OAEG;IACH,KAAK;IAQL;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;;;;;;;OASG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,OAAO;IAiB/D;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAQ/B"}
package/dist/web/Sumor.js CHANGED
@@ -17,11 +17,13 @@ export class Sumor {
17
17
  constructor() {
18
18
  this.endpoint = '';
19
19
  this.authorizeUrl = '';
20
+ this.user = null;
20
21
  this.loaded = false;
21
22
  this.loadTime = 0;
22
23
  this.CACHE_TTL = 3600000; // 1小时,单位毫秒
23
24
  this.isRefreshing = false;
24
25
  this.refreshSubscribers = [];
26
+ this.userChangeSubscribers = [];
25
27
  console.log('初始化轻呈云客户端...');
26
28
  this.axios = this.createAxiosInstance();
27
29
  }
@@ -32,6 +34,26 @@ export class Sumor {
32
34
  this.refreshSubscribers.forEach(callback => callback());
33
35
  this.refreshSubscribers = [];
34
36
  }
37
+ /**
38
+ * 订阅用户变化事件
39
+ * @param callback 用户变化时的回调函数
40
+ */
41
+ onUserChange(callback) {
42
+ this.userChangeSubscribers.push(callback);
43
+ }
44
+ /**
45
+ * 触发用户变化事件
46
+ */
47
+ emitUserChange() {
48
+ this.userChangeSubscribers.forEach(callback => {
49
+ try {
50
+ callback(this.user);
51
+ }
52
+ catch (error) {
53
+ console.error('User change callback error:', error);
54
+ }
55
+ });
56
+ }
35
57
  /**
36
58
  * 创建 Axios 实例并配置拦截器
37
59
  */
@@ -75,6 +97,15 @@ export class Sumor {
75
97
  });
76
98
  const response = await refreshInstance.put('/api/oauth/token', {});
77
99
  if (response.status === 200) {
100
+ // 如果响应中包含新的用户信息,更新本地状态
101
+ if (response.data && response.data.data && response.data.data.user) {
102
+ const previousUser = this.user;
103
+ this.user = response.data.data.user;
104
+ // 如果用户信息发生变化,触发回调
105
+ if (this.user !== previousUser) {
106
+ this.emitUserChange();
107
+ }
108
+ }
78
109
  this.isRefreshing = false;
79
110
  this.onTokenRefreshed();
80
111
  return instance(originalRequest);
@@ -86,6 +117,9 @@ export class Sumor {
86
117
  catch (refreshError) {
87
118
  this.isRefreshing = false;
88
119
  this.refreshSubscribers = [];
120
+ // 清空用户信息,表示已退出登录
121
+ this.user = null;
122
+ this.emitUserChange();
89
123
  const apiError = new ApiError('令牌已过期,请重新登录', 'TOKEN_REFRESH_FAILED', 401);
90
124
  return Promise.reject(apiError);
91
125
  }
@@ -138,22 +172,49 @@ export class Sumor {
138
172
  const now = Date.now();
139
173
  return now - this.loadTime < this.CACHE_TTL;
140
174
  }
141
- async init() {
142
- // 如果缓存仍然有效,直接返回
143
- if (this.isCacheValid()) {
175
+ /**
176
+ * 刷新 OAuth 信息和用户状态
177
+ * 通过刷新 access token 接口获取 endpoint、authorizeUrl 和用户信息
178
+ * @param force 是否强制刷新,忽略缓存
179
+ */
180
+ async refreshToken(force = false) {
181
+ // 如果缓存仍然有效且不是强制刷新,直接返回
182
+ if (!force && this.isCacheValid()) {
144
183
  return;
145
184
  }
185
+ const previousUser = this.user;
146
186
  try {
147
- const response = await axios.get('/api/oauth/info');
148
- if (response.data && response.data.data) {
149
- this.endpoint = response.data.data.endpoint;
150
- this.authorizeUrl = response.data.data.authorizeUrl;
187
+ // 直接调用 PUT /api/oauth/token 刷新接口
188
+ // 浏览器会自动在请求中包含 HttpOnly Cookie 中的 refresh_token
189
+ console.log('[Sumor] Calling PUT /api/oauth/token...');
190
+ const response = await this.axios.put('/api/oauth/token', {});
191
+ console.log('[Sumor] Response received:', response);
192
+ // 响应已被拦截器处理,返回的是 { endpoint, authorizeUrl, user }
193
+ if (response) {
194
+ const data = response;
195
+ this.endpoint = data.endpoint || '';
196
+ this.authorizeUrl = data.authorizeUrl || '';
197
+ this.user = data.user || null;
198
+ console.log('[Sumor] User info updated:', this.user);
151
199
  }
152
200
  this.loaded = true;
153
201
  this.loadTime = Date.now();
202
+ // 如果用户信息发生变化,触发回调
203
+ if (this.user !== previousUser) {
204
+ console.log('[Sumor] User changed, emitting event');
205
+ this.emitUserChange();
206
+ }
154
207
  }
155
208
  catch (error) {
156
- console.error('Failed to load config:', error);
209
+ console.error('[Sumor] Failed to refresh OAuth info:', error);
210
+ // 刷新失败时,清除用户信息(401 表示未认证)
211
+ if (error.response?.status === 401 || error.code === 'TOKEN_REFRESH_FAILED') {
212
+ console.log('[Sumor] Token refresh failed or unauthorized, clearing user');
213
+ if (this.user !== null) {
214
+ this.user = null;
215
+ this.emitUserChange();
216
+ }
217
+ }
157
218
  }
158
219
  }
159
220
  getAvatarUrl(id) {
@@ -194,14 +255,52 @@ export class Sumor {
194
255
  // 即使请求失败,仍然返回(由调用方处理清除本地状态)
195
256
  throw error;
196
257
  }
258
+ finally {
259
+ // 清空本地用户信息
260
+ this.user = null;
261
+ this.emitUserChange();
262
+ }
197
263
  }
198
264
  /**
199
265
  * 手动刷新配置(用于处理长期运行的应用需要更新配置的情况)
200
266
  */
201
267
  async refreshConfig() {
202
- this.loaded = false;
203
- this.loadTime = 0;
204
- await this.init();
268
+ await this.refreshToken(true);
269
+ }
270
+ /**
271
+ * 检查用户是否有特定权限
272
+ * @param module 模块名称(如:posts、comments)
273
+ * @param operation 操作名称(如:view、edit、delete),为 * 或不传时表示检查模块的任何权限
274
+ * @returns 是否拥有权限
275
+ *
276
+ * 例如:
277
+ * - hasPermission('posts', 'edit') 检查是否有 'posts:edit' 权限
278
+ * - hasPermission('posts', '*') 或 hasPermission('posts') 检查是否有任何 posts 权限
279
+ */
280
+ hasPermission(module, operation = '*') {
281
+ if (!this.user || !this.user.permissions) {
282
+ return false;
283
+ }
284
+ const userPermissions = this.user.permissions.split(',').map(p => p.trim());
285
+ // 如果 operation 为 *,检查是否有该模块的任何权限
286
+ if (operation === '*') {
287
+ return userPermissions.some(permission => permission.startsWith(`${module}:`));
288
+ }
289
+ // 否则检查特定的 module:operation 权限
290
+ const requiredPermission = `${module}:${operation}`;
291
+ return userPermissions.includes(requiredPermission);
292
+ }
293
+ /**
294
+ * 检查用户是否拥有指定角色
295
+ * @param role 角色名称
296
+ * @returns 是否拥有该角色
297
+ */
298
+ hasRole(role) {
299
+ if (!this.user || !this.user.roles) {
300
+ return false;
301
+ }
302
+ const userRoles = this.user.roles.split(',');
303
+ return userRoles.some(r => r.trim() === role);
205
304
  }
206
305
  }
207
306
  //# sourceMappingURL=Sumor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sumor.js","sourceRoot":"","sources":["../../web/Sumor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Sumor.js","sourceRoot":"","sources":["../../web/Sumor.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../web/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAsB,UAAU,kBAU/B;AAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../web/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAsB,UAAU,kBAa/B;AAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA"}
package/dist/web/index.js CHANGED
@@ -3,11 +3,14 @@
3
3
  */
4
4
  import { Sumor } from './Sumor';
5
5
  export async function setupSumor() {
6
+ console.log('[setupSumor] Creating Sumor instance...');
6
7
  const sumor = new Sumor();
7
8
  // 初始化 Sumor
8
- await sumor.init();
9
+ console.log('[setupSumor] Calling refreshToken...');
10
+ await sumor.refreshToken();
9
11
  // 挂载到全局 window 对象
10
12
  window.sumor = sumor;
13
+ console.log('[setupSumor] Sumor initialized, window.sumor.user:', window.sumor.user);
11
14
  console.log('✓ 完成轻呈云客户端初始化');
12
15
  }
13
16
  export { Sumor, ApiError } from './Sumor';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../web/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/B,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAA;IAEzB,YAAY;IACZ,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;IAElB,kBAAkB;IAClB,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;IAEpB,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;AAC9B,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../web/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAE/B,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAA;IAEzB,YAAY;IACZ,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAA;IACnD,MAAM,KAAK,CAAC,YAAY,EAAE,CAAA;IAE1B,kBAAkB;IAClB,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;IAEpB,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACpF,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;AAC9B,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sumor",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "description": "Sumor OAuth framework",
5
5
  "main": "dist/server/index.js",
6
6
  "types": "dist/server/index.d.ts",
@@ -1,12 +0,0 @@
1
- /**
2
- * OAuth 信息控制器
3
- * 获取 ITS 端点信息
4
- */
5
- /**
6
- * 获取 ITS 配置信息
7
- * GET /api/oauth/info
8
- *
9
- * 无需认证 - 在 JWT 中间件之前调用
10
- */
11
- export declare const getItsInfo: (req: any, res: any, next: any) => Promise<void>;
12
- //# sourceMappingURL=infoController.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"infoController.d.ts","sourceRoot":"","sources":["../../../server/controllers/infoController.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkEH;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAU,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,kBAc7D,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"infoController.js","sourceRoot":"","sources":["../../../server/controllers/infoController.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,oDAA2B;AAC3B,4CAAgD;AAEhD;;GAEG;AACH,SAAS,qBAAqB;IAI5B,MAAM,YAAY,GAAG,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3D,MAAM,SAAS,GAAG,gBAAM;SACrB,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,YAAY,CAAC;SACpB,MAAM,CAAC,QAAQ,CAAC;SAChB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IAEpB,OAAO;QACL,aAAa,EAAE,SAAS;QACxB,YAAY,EAAE,YAAY;KAC3B,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa;IACpB,OAAO,gBAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC/C,CAAC;AAED;;;GAGG;AACH,SAAS,wBAAwB;IAC/B,MAAM,WAAW,GAAG,IAAA,uBAAc,GAAE,CAAA;IACpC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,qBAAqB,EAAE,CAAA;IAE/D,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,CAAA;IAEnC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAClD,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,EAAE,CAAA;IACnC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,WAAW,CAAA;IAEvF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,WAAW,EAAE,GAAG;QAChB,YAAY,EAAE,MAAM;QACpB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,cAAc;QACrB,aAAa,EAAE,aAAa;QAC5B,mBAAmB,EAAE,MAAM;KAC5B,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,GAAG,WAAW,CAAC,OAAO,cAAc,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAA;IAEvE,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;GAKG;AACI,MAAM,UAAU,GAAG,KAAK,EAAE,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;IAChE,IAAI,CAAC;QACH,MAAM,iBAAiB,GAAG,wBAAwB,EAAE,CAAA;QAEpD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,IAAI;YACV,IAAI,EAAE;gBACJ,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ;gBAClC,YAAY,EAAE,iBAAiB;aAChC;SACF,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,CAAC,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAdY,QAAA,UAAU,cActB"}