sumor 3.3.3 → 3.3.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 +53 -0
- package/README.zh-CN.md +61 -7
- package/dist/server/controllers/logoutController.js +2 -2
- package/dist/server/controllers/oauthCallbackController.js +2 -2
- package/dist/server/controllers/tokenRefreshController.js +2 -2
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/models/blacklistModel.js +2 -2
- package/dist/server/models/jwksModel.js +2 -2
- package/dist/server/services/OAuthService.d.ts +24 -0
- package/dist/server/services/OAuthService.d.ts.map +1 -0
- package/dist/server/services/OAuthService.js +32 -0
- package/dist/server/services/OAuthService.js.map +1 -0
- package/dist/server/services/oauth/MockDataGenerator.d.ts +18 -0
- package/dist/server/services/oauth/MockDataGenerator.d.ts.map +1 -0
- package/dist/server/services/oauth/MockDataGenerator.js +39 -0
- package/dist/server/services/oauth/MockDataGenerator.js.map +1 -0
- package/dist/server/services/oauth/OAuthMockService.d.ts +28 -0
- package/dist/server/services/oauth/OAuthMockService.d.ts.map +1 -0
- package/dist/server/services/oauth/OAuthMockService.js +184 -0
- package/dist/server/services/oauth/OAuthMockService.js.map +1 -0
- package/dist/server/services/oauth/OAuthProductionService.d.ts +22 -0
- package/dist/server/services/oauth/OAuthProductionService.d.ts.map +1 -0
- package/dist/server/services/oauth/OAuthProductionService.js +203 -0
- package/dist/server/services/oauth/OAuthProductionService.js.map +1 -0
- package/dist/server/services/oauth/OAuthServiceError.d.ts +9 -0
- package/dist/server/services/oauth/OAuthServiceError.d.ts.map +1 -0
- package/dist/server/services/oauth/OAuthServiceError.js +16 -0
- package/dist/server/services/oauth/OAuthServiceError.js.map +1 -0
- package/package.json +1 -1
- package/dist/server/services/oauthService.d.ts +0 -149
- package/dist/server/services/oauthService.d.ts.map +0 -1
- package/dist/server/services/oauthService.js +0 -360
- package/dist/server/services/oauthService.js.map +0 -1
package/README.md
CHANGED
|
@@ -445,6 +445,43 @@ OAUTH_MOCK_USER_IS_VERIFIED=1
|
|
|
445
445
|
|
|
446
446
|
### Example Mock Setup
|
|
447
447
|
|
|
448
|
+
#### Mock Users List
|
|
449
|
+
|
|
450
|
+
To populate the `getUserInfo()`, `getUsersInfo()`, and `searchUsers()` methods with test data, configure the `OAUTH_MOCK_USERS` environment variable with a JSON array of user objects.
|
|
451
|
+
|
|
452
|
+
**User object properties:**
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
interface MockUser {
|
|
456
|
+
userId: string // Required: unique user identifier
|
|
457
|
+
username?: string // Optional: defaults to `user_{userId}`
|
|
458
|
+
email?: string // Optional: defaults to `{userId}@example.com`
|
|
459
|
+
name?: string // Optional: defaults to `User {userId}`
|
|
460
|
+
avatar?: string // Optional: avatar URL
|
|
461
|
+
phone?: string // Optional: phone number
|
|
462
|
+
createdAt?: string // Optional: ISO 8601 timestamp
|
|
463
|
+
updatedAt?: string // Optional: ISO 8601 timestamp
|
|
464
|
+
isActive?: boolean // Optional: defaults to `true`
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**Behavior:**
|
|
469
|
+
|
|
470
|
+
- `getUserInfo('user001')` returns the configured user object if it exists, otherwise generates a default user
|
|
471
|
+
- `getUsersInfo(['user001', 'unknown'])` returns configured users for known IDs and generated users for unknown IDs
|
|
472
|
+
- `searchUsers('alice')` searches configured users by userId, username, name, or email and returns matches
|
|
473
|
+
|
|
474
|
+
**Configuration example:**
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
export OAUTH_MOCK_USERS='[
|
|
478
|
+
{"userId": "user001", "username": "alice", "email": "alice@example.com", "name": "Alice Wang"},
|
|
479
|
+
{"userId": "user002", "username": "bob", "email": "bob@example.com", "name": "Bob Smith"}
|
|
480
|
+
]'
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
For comprehensive examples and usage patterns, refer to [Mock Users List Usage Guide](server/services/oauth/MOCK_USERS_USAGE.md).
|
|
484
|
+
|
|
448
485
|
**.env.development:**
|
|
449
486
|
|
|
450
487
|
```bash
|
|
@@ -453,6 +490,22 @@ OAUTH_MOCK_USER_ID=dev-user-1
|
|
|
453
490
|
OAUTH_MOCK_USER_ROLES=admin
|
|
454
491
|
OAUTH_MOCK_USER_PERMISSIONS=posts:view,posts:edit,posts:delete
|
|
455
492
|
OAUTH_MOCK_USER_IS_VERIFIED=1
|
|
493
|
+
OAUTH_MOCK_USERS='[
|
|
494
|
+
{
|
|
495
|
+
"userId": "user001",
|
|
496
|
+
"username": "alice",
|
|
497
|
+
"email": "alice@example.com",
|
|
498
|
+
"name": "Alice Wang",
|
|
499
|
+
"avatar": "https://api.example.com/avatars/alice.jpg",
|
|
500
|
+
"isActive": true
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"userId": "user002",
|
|
504
|
+
"username": "bob",
|
|
505
|
+
"email": "bob@example.com",
|
|
506
|
+
"name": "Bob Smith"
|
|
507
|
+
}
|
|
508
|
+
]'
|
|
456
509
|
```
|
|
457
510
|
|
|
458
511
|
No changes are needed in application code — the same `oauthRoutes`, `loadJwtUserMiddleware`, `login()`, and `logout()` calls work in both mock and production modes.
|
package/README.zh-CN.md
CHANGED
|
@@ -425,13 +425,14 @@ OAUTH_MOCK_USER_PERMISSIONS=
|
|
|
425
425
|
OAUTH_MOCK_USER_IS_VERIFIED=1
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
-
| 变量 | 默认值 | 说明
|
|
429
|
-
| ----------------------------- | --------------- |
|
|
430
|
-
| `OAUTH_MOCK` | `false` | 设为 `true` 启用 Mock 模式
|
|
431
|
-
| `OAUTH_MOCK_USER_ID` | `mock-user-001` | Mock 用户 ID
|
|
432
|
-
| `OAUTH_MOCK_USER_ROLES` | `admin` | 逗号分隔的 Mock 角色
|
|
433
|
-
| `OAUTH_MOCK_USER_PERMISSIONS` | _(空)_ | 逗号分隔的 Mock 权限
|
|
434
|
-
| `OAUTH_MOCK_USER_IS_VERIFIED` | `1` | Mock 认证状态(`0` 或 `1`)
|
|
428
|
+
| 变量 | 默认值 | 说明 |
|
|
429
|
+
| ----------------------------- | --------------- | ------------------------------------------- |
|
|
430
|
+
| `OAUTH_MOCK` | `false` | 设为 `true` 启用 Mock 模式 |
|
|
431
|
+
| `OAUTH_MOCK_USER_ID` | `mock-user-001` | Mock 用户 ID |
|
|
432
|
+
| `OAUTH_MOCK_USER_ROLES` | `admin` | 逗号分隔的 Mock 角色 |
|
|
433
|
+
| `OAUTH_MOCK_USER_PERMISSIONS` | _(空)_ | 逗号分隔的 Mock 权限 |
|
|
434
|
+
| `OAUTH_MOCK_USER_IS_VERIFIED` | `1` | Mock 认证状态(`0` 或 `1`) |
|
|
435
|
+
| `OAUTH_MOCK_USERS` | _(空)_ | JSON 数组格式的 Mock 用户列表用于搜索和查询 |
|
|
435
436
|
|
|
436
437
|
### Mock 专用路由(仅在 `OAUTH_MOCK=true` 时注册)
|
|
437
438
|
|
|
@@ -444,6 +445,43 @@ OAUTH_MOCK_USER_IS_VERIFIED=1
|
|
|
444
445
|
|
|
445
446
|
### Mock 模式示例配置
|
|
446
447
|
|
|
448
|
+
#### Mock 用户列表
|
|
449
|
+
|
|
450
|
+
通过配置 `OAUTH_MOCK_USERS` 环境变量为 `getUserInfo()`、`getUsersInfo()` 和 `searchUsers()` 方法提供测试数据,无需真实 OAuth 服务。
|
|
451
|
+
|
|
452
|
+
**用户对象属性:**
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
interface MockUser {
|
|
456
|
+
userId: string // 必需:用户唯一标识
|
|
457
|
+
username?: string // 可选:默认为 `user_{userId}`
|
|
458
|
+
email?: string // 可选:默认为 `{userId}@example.com`
|
|
459
|
+
name?: string // 可选:默认为 `User {userId}`
|
|
460
|
+
avatar?: string // 可选:头像 URL
|
|
461
|
+
phone?: string // 可选:电话号码
|
|
462
|
+
createdAt?: string // 可选:ISO 8601 时间戳
|
|
463
|
+
updatedAt?: string // 可选:ISO 8601 时间戳
|
|
464
|
+
isActive?: boolean // 可选:默认为 `true`
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**行为说明:**
|
|
469
|
+
|
|
470
|
+
- `getUserInfo('user001')` 返回配置的用户对象,不存在则生成默认用户
|
|
471
|
+
- `getUsersInfo(['user001', 'unknown'])` 返回已配置用户及动态生成的未知用户
|
|
472
|
+
- `searchUsers('alice')` 在配置用户中按 userId、username、name、email 模糊搜索并返回结果
|
|
473
|
+
|
|
474
|
+
**配置示例:**
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
export OAUTH_MOCK_USERS='[
|
|
478
|
+
{"userId": "user001", "username": "alice", "email": "alice@example.com", "name": "Alice Wang"},
|
|
479
|
+
{"userId": "user002", "username": "bob", "email": "bob@example.com", "name": "Bob Smith"}
|
|
480
|
+
]'
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
更详细的配置示例和使用模式参考 [Mock 用户列表使用指南](server/services/oauth/MOCK_USERS_USAGE.md)。
|
|
484
|
+
|
|
447
485
|
**.env.development:**
|
|
448
486
|
|
|
449
487
|
```bash
|
|
@@ -452,6 +490,22 @@ OAUTH_MOCK_USER_ID=dev-user-1
|
|
|
452
490
|
OAUTH_MOCK_USER_ROLES=admin
|
|
453
491
|
OAUTH_MOCK_USER_PERMISSIONS=posts:view,posts:edit,posts:delete
|
|
454
492
|
OAUTH_MOCK_USER_IS_VERIFIED=1
|
|
493
|
+
OAUTH_MOCK_USERS='[
|
|
494
|
+
{
|
|
495
|
+
"userId": "user001",
|
|
496
|
+
"username": "alice",
|
|
497
|
+
"email": "alice@example.com",
|
|
498
|
+
"name": "Alice Wang",
|
|
499
|
+
"avatar": "https://api.example.com/avatars/alice.jpg",
|
|
500
|
+
"isActive": true
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"userId": "user002",
|
|
504
|
+
"username": "bob",
|
|
505
|
+
"email": "bob@example.com",
|
|
506
|
+
"name": "Bob Smith"
|
|
507
|
+
}
|
|
508
|
+
]'
|
|
455
509
|
```
|
|
456
510
|
|
|
457
511
|
应用代码无需任何修改 —— 相同的 `oauthRoutes`、`loadJwtUserMiddleware`、`login()` 和 `logout()` 调用在 Mock 模式和生产模式下均正常工作。
|
|
@@ -7,7 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
};
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.logout = logout;
|
|
10
|
-
const
|
|
10
|
+
const OAuthService_1 = __importDefault(require("../services/OAuthService"));
|
|
11
11
|
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
12
12
|
/**
|
|
13
13
|
* 用户登出
|
|
@@ -42,7 +42,7 @@ async function logout(req, res) {
|
|
|
42
42
|
const decoded = (0, jsonwebtoken_1.decode)(accessToken);
|
|
43
43
|
const sessionId = decoded?.sessionId;
|
|
44
44
|
if (sessionId) {
|
|
45
|
-
const oauthService = new
|
|
45
|
+
const oauthService = new OAuthService_1.default();
|
|
46
46
|
await oauthService.revokeSession(sessionId);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -11,7 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.default = oauthCallbackController;
|
|
14
|
-
const
|
|
14
|
+
const OAuthService_1 = __importDefault(require("../services/OAuthService"));
|
|
15
15
|
const tokenModel_1 = require("../models/tokenModel");
|
|
16
16
|
const config_1 = require("../utils/config");
|
|
17
17
|
const oauthTokenUtils_1 = require("../utils/oauthTokenUtils");
|
|
@@ -30,7 +30,7 @@ async function exchangeCodeForToken(code, codeVerifier) {
|
|
|
30
30
|
// 使用配置中的 redirectUri
|
|
31
31
|
const oauthConfig = (0, config_1.getOAuthConfig)();
|
|
32
32
|
const uri = oauthConfig.redirectUri;
|
|
33
|
-
const oauthService = new
|
|
33
|
+
const oauthService = new OAuthService_1.default();
|
|
34
34
|
const data = await oauthService.exchangeCode('authorization_code', code, uri, verifier);
|
|
35
35
|
// 验证响应数据的完整性
|
|
36
36
|
if (!data || !data.accessToken || !data.tokenType || typeof data.expiresIn !== 'number') {
|
|
@@ -10,7 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.default = tokenRefreshController;
|
|
13
|
-
const
|
|
13
|
+
const OAuthService_1 = __importDefault(require("../services/OAuthService"));
|
|
14
14
|
const oauthTokenUtils_1 = require("../utils/oauthTokenUtils");
|
|
15
15
|
const tokenModel_1 = require("../models/tokenModel");
|
|
16
16
|
const config_1 = require("../utils/config");
|
|
@@ -55,7 +55,7 @@ async function tokenRefreshController(req, res) {
|
|
|
55
55
|
// 如果有有效的 refreshToken,进行刷新
|
|
56
56
|
if (refreshToken) {
|
|
57
57
|
// 使用 OAuthService 调用 OAuth API
|
|
58
|
-
const oauthService = new
|
|
58
|
+
const oauthService = new OAuthService_1.default();
|
|
59
59
|
const tokenData = await oauthService.refreshAccessToken(refreshToken);
|
|
60
60
|
// 使用公用的 token 设置函数
|
|
61
61
|
// 设置新的 accessToken
|
package/dist/server/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Sumor OAuth 暴露接口
|
|
3
3
|
* 导出所需的中间件、路由和服务供客户端使用
|
|
4
4
|
*/
|
|
5
|
-
import OAuthService from './services/
|
|
5
|
+
import OAuthService from './services/OAuthService';
|
|
6
6
|
import oauthRoutes from './routes';
|
|
7
7
|
import { loadJwtUserMiddleware } from './middlewares/loadJwtUserMiddleware';
|
|
8
8
|
/**
|
package/dist/server/index.js
CHANGED
|
@@ -8,8 +8,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.oauthRoutes = exports.loadJwtUserMiddleware = exports.OAuthService = void 0;
|
|
11
|
-
const
|
|
12
|
-
exports.OAuthService =
|
|
11
|
+
const OAuthService_1 = __importDefault(require("./services/OAuthService"));
|
|
12
|
+
exports.OAuthService = OAuthService_1.default;
|
|
13
13
|
const routes_1 = __importDefault(require("./routes"));
|
|
14
14
|
exports.oauthRoutes = routes_1.default;
|
|
15
15
|
const loadJwtUserMiddleware_1 = require("./middlewares/loadJwtUserMiddleware");
|
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.BlacklistModel = void 0;
|
|
16
16
|
exports.getBlacklistModel = getBlacklistModel;
|
|
17
|
-
const
|
|
17
|
+
const OAuthService_1 = __importDefault(require("../services/OAuthService"));
|
|
18
18
|
/**
|
|
19
19
|
* 黑名单查询模型
|
|
20
20
|
*/
|
|
@@ -81,7 +81,7 @@ class BlacklistModel {
|
|
|
81
81
|
*/
|
|
82
82
|
async performSessionIdCheck(sessionId) {
|
|
83
83
|
try {
|
|
84
|
-
const oauthService = new
|
|
84
|
+
const oauthService = new OAuthService_1.default();
|
|
85
85
|
const response = await oauthService.checkBlacklist(sessionId);
|
|
86
86
|
const isBlacklisted = response.data?.isBlacklisted || false;
|
|
87
87
|
return isBlacklisted;
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.getPublicKey = getPublicKey;
|
|
14
14
|
const crypto_1 = __importDefault(require("crypto"));
|
|
15
|
-
const
|
|
15
|
+
const OAuthService_1 = __importDefault(require("../services/OAuthService"));
|
|
16
16
|
let cachedPublicKey = null;
|
|
17
17
|
/**
|
|
18
18
|
* 获取用于验证 Token 的公钥(PEM 格式)
|
|
@@ -32,7 +32,7 @@ async function getPublicKey() {
|
|
|
32
32
|
return cachedPublicKey;
|
|
33
33
|
}
|
|
34
34
|
// 获取 JWKS
|
|
35
|
-
const oauthService = new
|
|
35
|
+
const oauthService = new OAuthService_1.default();
|
|
36
36
|
const jwks = await oauthService.getJWKS();
|
|
37
37
|
if (!jwks.keys || jwks.keys.length === 0) {
|
|
38
38
|
throw new Error('JWKS 中无可用的密钥');
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth 服务层
|
|
3
|
+
*
|
|
4
|
+
* 提供 OAuth 相关的业务操作,包括 Token 管理、黑名单检查等。
|
|
5
|
+
* 使用工厂模式自动区分 Mock 和 Production 环境:
|
|
6
|
+
* new OAuthService() 会自动根据 isMockMode() 返回正确的实例实现
|
|
7
|
+
*/
|
|
8
|
+
import { OAuthProductionService } from './oauth/OAuthProductionService';
|
|
9
|
+
import { OAuthMockService } from './oauth/OAuthMockService';
|
|
10
|
+
export { OAuthServiceError } from './oauth/OAuthServiceError';
|
|
11
|
+
type OAuthServiceType = OAuthProductionService | OAuthMockService;
|
|
12
|
+
/**
|
|
13
|
+
* OAuth 服务工厂函数
|
|
14
|
+
* 支持 both function call 和 new 调用:
|
|
15
|
+
* - OAuthService() or new OAuthService() 都返回正确的实例
|
|
16
|
+
* - 根据 isMockMode() 返回 OAuthMockService 或 OAuthProductionService
|
|
17
|
+
*/
|
|
18
|
+
interface OAuthServiceConstructor {
|
|
19
|
+
(): OAuthServiceType;
|
|
20
|
+
new (): OAuthServiceType;
|
|
21
|
+
}
|
|
22
|
+
declare const OAuthService: OAuthServiceConstructor;
|
|
23
|
+
export default OAuthService;
|
|
24
|
+
//# sourceMappingURL=OAuthService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthService.d.ts","sourceRoot":"","sources":["../../../server/services/OAuthService.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE7D,KAAK,gBAAgB,GAAG,sBAAsB,GAAG,gBAAgB,CAAA;AAEjE;;;;;GAKG;AACH,UAAU,uBAAuB;IAC/B,IAAI,gBAAgB,CAAA;IACpB,QAAQ,gBAAgB,CAAA;CACzB;AAED,QAAA,MAAM,YAAY,yBAiBd,CAAA;AAEJ,eAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OAuth 服务层
|
|
4
|
+
*
|
|
5
|
+
* 提供 OAuth 相关的业务操作,包括 Token 管理、黑名单检查等。
|
|
6
|
+
* 使用工厂模式自动区分 Mock 和 Production 环境:
|
|
7
|
+
* new OAuthService() 会自动根据 isMockMode() 返回正确的实例实现
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.OAuthServiceError = void 0;
|
|
11
|
+
const mockConfig_1 = require("../mock/mockConfig");
|
|
12
|
+
const OAuthProductionService_1 = require("./oauth/OAuthProductionService");
|
|
13
|
+
const OAuthMockService_1 = require("./oauth/OAuthMockService");
|
|
14
|
+
var OAuthServiceError_1 = require("./oauth/OAuthServiceError");
|
|
15
|
+
Object.defineProperty(exports, "OAuthServiceError", { enumerable: true, get: function () { return OAuthServiceError_1.OAuthServiceError; } });
|
|
16
|
+
const OAuthService = (function () {
|
|
17
|
+
const factory = () => {
|
|
18
|
+
if ((0, mockConfig_1.isMockMode)()) {
|
|
19
|
+
return new OAuthMockService_1.OAuthMockService();
|
|
20
|
+
}
|
|
21
|
+
return new OAuthProductionService_1.OAuthProductionService();
|
|
22
|
+
};
|
|
23
|
+
// 同时支持函数调用和 new 调用
|
|
24
|
+
const Fn = function () {
|
|
25
|
+
return factory();
|
|
26
|
+
};
|
|
27
|
+
// 也支持 new 调用
|
|
28
|
+
Fn.prototype.constructor = factory;
|
|
29
|
+
return Fn;
|
|
30
|
+
})();
|
|
31
|
+
exports.default = OAuthService;
|
|
32
|
+
//# sourceMappingURL=OAuthService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthService.js","sourceRoot":"","sources":["../../../server/services/OAuthService.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,mDAA+C;AAC/C,2EAAuE;AACvE,+DAA2D;AAE3D,+DAA6D;AAApD,sHAAA,iBAAiB,OAAA;AAe1B,MAAM,YAAY,GAAG,CAAC;IACpB,MAAM,OAAO,GAAG,GAAqB,EAAE;QACrC,IAAI,IAAA,uBAAU,GAAE,EAAE,CAAC;YACjB,OAAO,IAAI,mCAAgB,EAAE,CAAA;QAC/B,CAAC;QACD,OAAO,IAAI,+CAAsB,EAAE,CAAA;IACrC,CAAC,CAAA;IAED,mBAAmB;IACnB,MAAM,EAAE,GAAG;QACT,OAAO,OAAO,EAAE,CAAA;IAClB,CAAmC,CAAA;IAEnC,aAAa;IACb,EAAE,CAAC,SAAS,CAAC,WAAW,GAAG,OAAO,CAAA;IAElC,OAAO,EAAE,CAAA;AACX,CAAC,CAAC,EAAE,CAAA;AAEJ,kBAAe,YAAY,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock 数据生成工具
|
|
3
|
+
* 参考 ITS 项目最佳实践,生成更真实的测试数据
|
|
4
|
+
*/
|
|
5
|
+
export declare class MockDataGenerator {
|
|
6
|
+
static generateAccessToken(): string;
|
|
7
|
+
static generateRefreshToken(): string;
|
|
8
|
+
static generateJti(): string;
|
|
9
|
+
static generateMsgId(): number;
|
|
10
|
+
static generateOpenId(): string;
|
|
11
|
+
static generateRandomBase64(): string;
|
|
12
|
+
static generateRSAKeyPair(): {
|
|
13
|
+
publicKey: string;
|
|
14
|
+
privateKey: string;
|
|
15
|
+
kid: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=MockDataGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MockDataGenerator.d.ts","sourceRoot":"","sources":["../../../../server/services/oauth/MockDataGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,qBAAa,iBAAiB;IAC5B,MAAM,CAAC,mBAAmB,IAAI,MAAM;IAIpC,MAAM,CAAC,oBAAoB,IAAI,MAAM;IAIrC,MAAM,CAAC,WAAW,IAAI,MAAM;IAI5B,MAAM,CAAC,aAAa,IAAI,MAAM;IAI9B,MAAM,CAAC,cAAc,IAAI,MAAM;IAI/B,MAAM,CAAC,oBAAoB,IAAI,MAAM;IAIrC,MAAM,CAAC,kBAAkB,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;CAWpF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mock 数据生成工具
|
|
4
|
+
* 参考 ITS 项目最佳实践,生成更真实的测试数据
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MockDataGenerator = void 0;
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
|
+
class MockDataGenerator {
|
|
10
|
+
static generateAccessToken() {
|
|
11
|
+
return `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiR7cmFuZG9tVVVJRCgpfSJ9.${this.generateRandomBase64()}`;
|
|
12
|
+
}
|
|
13
|
+
static generateRefreshToken() {
|
|
14
|
+
return `refresh_${(0, crypto_1.randomUUID)().replace(/-/g, '')}`;
|
|
15
|
+
}
|
|
16
|
+
static generateJti() {
|
|
17
|
+
return (0, crypto_1.randomUUID)();
|
|
18
|
+
}
|
|
19
|
+
static generateMsgId() {
|
|
20
|
+
return Math.floor(Math.random() * 9000000000) + 1000000000;
|
|
21
|
+
}
|
|
22
|
+
static generateOpenId() {
|
|
23
|
+
return `openid_${(0, crypto_1.randomBytes)(16).toString('hex')}`;
|
|
24
|
+
}
|
|
25
|
+
static generateRandomBase64() {
|
|
26
|
+
return (0, crypto_1.randomBytes)(32).toString('base64').replace(/[+/]/g, '').substring(0, 43);
|
|
27
|
+
}
|
|
28
|
+
static generateRSAKeyPair() {
|
|
29
|
+
const { publicKey, privateKey } = (0, crypto_1.generateKeyPairSync)('rsa', {
|
|
30
|
+
modulusLength: 2048,
|
|
31
|
+
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
32
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
33
|
+
});
|
|
34
|
+
const kid = `mock_${Date.now().toString(36)}_${(0, crypto_1.randomBytes)(4).toString('hex')}`;
|
|
35
|
+
return { publicKey, privateKey, kid };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.MockDataGenerator = MockDataGenerator;
|
|
39
|
+
//# sourceMappingURL=MockDataGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MockDataGenerator.js","sourceRoot":"","sources":["../../../../server/services/oauth/MockDataGenerator.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mCAAqE;AAErE,MAAa,iBAAiB;IAC5B,MAAM,CAAC,mBAAmB;QACxB,OAAO,wEAAwE,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAA;IAC9G,CAAC;IAED,MAAM,CAAC,oBAAoB;QACzB,OAAO,WAAW,IAAA,mBAAU,GAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,MAAM,CAAC,WAAW;QAChB,OAAO,IAAA,mBAAU,GAAE,CAAA;IACrB,CAAC;IAED,MAAM,CAAC,aAAa;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,UAAU,CAAA;IAC5D,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,OAAO,UAAU,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,MAAM,CAAC,oBAAoB;QACzB,OAAO,IAAA,oBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACjF,CAAC;IAED,MAAM,CAAC,kBAAkB;QACvB,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAA,4BAAmB,EAAC,KAAK,EAAE;YAC3D,aAAa,EAAE,IAAI;YACnB,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;YAClD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;SACrD,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAA;QAE/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,CAAA;IACvC,CAAC;CACF;AApCD,8CAoCC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth Mock 服务
|
|
3
|
+
* 用于测试环境,返回真实格式的模拟数据
|
|
4
|
+
* 参考 ITS 项目实现,使用加密生成和随机数据
|
|
5
|
+
*/
|
|
6
|
+
import type { ITokenResponse, IJWKSResponse, IBlacklistCheckResponse, ISendWechatMessageResponse, IBroadcastWechatMessageResponse } from '../../types/oauth';
|
|
7
|
+
export declare class OAuthMockService {
|
|
8
|
+
private mockUsers;
|
|
9
|
+
constructor();
|
|
10
|
+
private loadMockUsers;
|
|
11
|
+
private getMockUser;
|
|
12
|
+
private generateDefaultUser;
|
|
13
|
+
exchangeCode(grantType: string, code: string, redirectUri: string, codeVerifier: string): Promise<ITokenResponse>;
|
|
14
|
+
getJWKS(): Promise<IJWKSResponse>;
|
|
15
|
+
checkBlacklist(sessionId: string): Promise<IBlacklistCheckResponse>;
|
|
16
|
+
revokeSession(sessionId: string): Promise<void>;
|
|
17
|
+
refreshAccessToken(refreshToken: string): Promise<ITokenResponse>;
|
|
18
|
+
sendWechatMessage(templateId: string, userId: string, data: Record<string, any>, url?: string): Promise<ISendWechatMessageResponse>;
|
|
19
|
+
broadcastWechatMessage(templateId: string, data: Record<string, {
|
|
20
|
+
value: string;
|
|
21
|
+
}>, roleIds: string[], url?: string): Promise<IBroadcastWechatMessageResponse>;
|
|
22
|
+
getUserInfo(userId: string): Promise<any>;
|
|
23
|
+
getUsersInfo(userIds: string[]): Promise<(any | null)[]>;
|
|
24
|
+
searchUsers(searchTerm: string, limit?: number): Promise<any[]>;
|
|
25
|
+
getPermissions(): Promise<any>;
|
|
26
|
+
updatePermissions(permissionsConfig: any): Promise<any>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=OAuthMockService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthMockService.d.ts","sourceRoot":"","sources":["../../../../server/services/oauth/OAuthMockService.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,uBAAuB,EACvB,0BAA0B,EAC1B,+BAA+B,EAChC,MAAM,mBAAmB,CAAA;AAc1B,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAoC;;IAMrD,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,mBAAmB;IAarB,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,cAAc,CAAC;IAWpB,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IAiBjC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAUnE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/C,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWjE,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,0BAA0B,CAAC;IAUhC,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EACvC,OAAO,EAAE,MAAM,EAAE,EACjB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,+BAA+B,CAAC;IAoBrC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IASzC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;IAexD,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IA8BnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAI9B,iBAAiB,CAAC,iBAAiB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;CAG9D"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OAuth Mock 服务
|
|
4
|
+
* 用于测试环境,返回真实格式的模拟数据
|
|
5
|
+
* 参考 ITS 项目实现,使用加密生成和随机数据
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.OAuthMockService = void 0;
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const MockDataGenerator_1 = require("./MockDataGenerator");
|
|
11
|
+
class OAuthMockService {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.mockUsers = new Map();
|
|
14
|
+
this.loadMockUsers();
|
|
15
|
+
}
|
|
16
|
+
loadMockUsers() {
|
|
17
|
+
const mockUsersJson = process.env.OAUTH_MOCK_USERS;
|
|
18
|
+
if (mockUsersJson) {
|
|
19
|
+
try {
|
|
20
|
+
const users = JSON.parse(mockUsersJson);
|
|
21
|
+
users.forEach(user => {
|
|
22
|
+
if (user.userId) {
|
|
23
|
+
this.mockUsers.set(user.userId, {
|
|
24
|
+
userId: user.userId,
|
|
25
|
+
username: user.username || `user_${user.userId}`,
|
|
26
|
+
email: user.email || `${user.userId}@example.com`,
|
|
27
|
+
name: user.name || `User ${user.userId}`,
|
|
28
|
+
avatar: user.avatar || `https://api.example.com/avatar/${user.userId}`,
|
|
29
|
+
phone: user.phone || `1${Math.floor(Math.random() * 9000000000 + 1000000000)}`,
|
|
30
|
+
createdAt: user.createdAt ||
|
|
31
|
+
new Date(Date.now() - Math.random() * 86400000 * 365).toISOString(),
|
|
32
|
+
updatedAt: user.updatedAt || new Date().toISOString(),
|
|
33
|
+
isActive: user.isActive !== false
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.warn('Failed to parse OAUTH_MOCK_USERS environment variable:', error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
getMockUser(userId) {
|
|
44
|
+
if (this.mockUsers.has(userId)) {
|
|
45
|
+
return this.mockUsers.get(userId) || null;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
generateDefaultUser(userId) {
|
|
50
|
+
return {
|
|
51
|
+
userId,
|
|
52
|
+
username: `user_${userId}`,
|
|
53
|
+
email: `${userId}@example.com`,
|
|
54
|
+
name: `User ${userId}`,
|
|
55
|
+
avatar: `https://api.example.com/avatar/${userId}`,
|
|
56
|
+
phone: `1${Math.floor(Math.random() * 9000000000 + 1000000000)}`,
|
|
57
|
+
createdAt: new Date(Date.now() - Math.random() * 86400000 * 365).toISOString(),
|
|
58
|
+
updatedAt: new Date().toISOString(),
|
|
59
|
+
isActive: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async exchangeCode(grantType, code, redirectUri, codeVerifier) {
|
|
63
|
+
return {
|
|
64
|
+
accessToken: MockDataGenerator_1.MockDataGenerator.generateAccessToken(),
|
|
65
|
+
refreshToken: MockDataGenerator_1.MockDataGenerator.generateRefreshToken(),
|
|
66
|
+
tokenType: 'Bearer',
|
|
67
|
+
expiresIn: 3600,
|
|
68
|
+
jti: MockDataGenerator_1.MockDataGenerator.generateJti(),
|
|
69
|
+
sessionId: (0, crypto_1.randomUUID)()
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async getJWKS() {
|
|
73
|
+
const { publicKey, kid } = MockDataGenerator_1.MockDataGenerator.generateRSAKeyPair();
|
|
74
|
+
return {
|
|
75
|
+
keys: [
|
|
76
|
+
{
|
|
77
|
+
kty: 'RSA',
|
|
78
|
+
use: 'sig',
|
|
79
|
+
kid,
|
|
80
|
+
n: (0, crypto_1.randomBytes)(256).toString('base64'),
|
|
81
|
+
e: 'AQAB',
|
|
82
|
+
alg: 'RS256'
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async checkBlacklist(sessionId) {
|
|
88
|
+
return {
|
|
89
|
+
code: '0',
|
|
90
|
+
data: {
|
|
91
|
+
sessionId,
|
|
92
|
+
isBlacklisted: false
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async revokeSession(sessionId) { }
|
|
97
|
+
async refreshAccessToken(refreshToken) {
|
|
98
|
+
return {
|
|
99
|
+
accessToken: MockDataGenerator_1.MockDataGenerator.generateAccessToken(),
|
|
100
|
+
refreshToken: MockDataGenerator_1.MockDataGenerator.generateRefreshToken(),
|
|
101
|
+
tokenType: 'Bearer',
|
|
102
|
+
expiresIn: 3600,
|
|
103
|
+
jti: MockDataGenerator_1.MockDataGenerator.generateJti(),
|
|
104
|
+
sessionId: (0, crypto_1.randomUUID)()
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async sendWechatMessage(templateId, userId, data, url) {
|
|
108
|
+
return {
|
|
109
|
+
code: '0',
|
|
110
|
+
message: 'success',
|
|
111
|
+
data: {
|
|
112
|
+
msgid: MockDataGenerator_1.MockDataGenerator.generateMsgId()
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
async broadcastWechatMessage(templateId, data, roleIds, url) {
|
|
117
|
+
const results = roleIds.map(userId => ({
|
|
118
|
+
userId,
|
|
119
|
+
openId: MockDataGenerator_1.MockDataGenerator.generateOpenId(),
|
|
120
|
+
success: true
|
|
121
|
+
}));
|
|
122
|
+
return {
|
|
123
|
+
code: '0',
|
|
124
|
+
message: 'success',
|
|
125
|
+
data: {
|
|
126
|
+
totalUsers: roleIds.length,
|
|
127
|
+
successCount: roleIds.length,
|
|
128
|
+
failureCount: 0,
|
|
129
|
+
successRate: '100%',
|
|
130
|
+
results
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
async getUserInfo(userId) {
|
|
135
|
+
if (!userId) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const mockUser = this.getMockUser(userId);
|
|
139
|
+
return mockUser || this.generateDefaultUser(userId);
|
|
140
|
+
}
|
|
141
|
+
async getUsersInfo(userIds) {
|
|
142
|
+
if (!userIds || userIds.length === 0) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
return userIds.map(id => {
|
|
146
|
+
if (!id) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const mockUser = this.getMockUser(id);
|
|
150
|
+
return mockUser || this.generateDefaultUser(id);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
async searchUsers(searchTerm, limit = 20) {
|
|
154
|
+
if (!searchTerm || searchTerm.trim() === '') {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const searchLower = searchTerm.toLowerCase();
|
|
158
|
+
const matchedUsers = [];
|
|
159
|
+
this.mockUsers.forEach(user => {
|
|
160
|
+
if (user.userId.toLowerCase().includes(searchLower) ||
|
|
161
|
+
user.username?.toLowerCase().includes(searchLower) ||
|
|
162
|
+
user.name?.toLowerCase().includes(searchLower) ||
|
|
163
|
+
user.email?.toLowerCase().includes(searchLower)) {
|
|
164
|
+
matchedUsers.push(user);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
if (matchedUsers.length > 0) {
|
|
168
|
+
return matchedUsers.slice(0, limit);
|
|
169
|
+
}
|
|
170
|
+
const count = Math.min(Math.floor(Math.random() * 5) + 1, limit);
|
|
171
|
+
return Array.from({ length: count }, (_, i) => {
|
|
172
|
+
const uid = `${searchTerm}_${i}`;
|
|
173
|
+
return this.generateDefaultUser(uid);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async getPermissions() {
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
async updatePermissions(permissionsConfig) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.OAuthMockService = OAuthMockService;
|
|
184
|
+
//# sourceMappingURL=OAuthMockService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthMockService.js","sourceRoot":"","sources":["../../../../server/services/oauth/OAuthMockService.ts"],"names":[],"mappings":"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"}
|