sumor 3.3.2 → 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/mock/avatarController.d.ts +8 -0
- package/dist/server/controllers/mock/avatarController.d.ts.map +1 -0
- package/dist/server/controllers/mock/avatarController.js +15 -0
- package/dist/server/controllers/mock/avatarController.js.map +1 -0
- package/dist/server/controllers/mock/loginController.d.ts +8 -0
- package/dist/server/controllers/mock/loginController.d.ts.map +1 -0
- package/dist/server/controllers/mock/loginController.js +34 -0
- package/dist/server/controllers/mock/loginController.js.map +1 -0
- package/dist/server/controllers/mock/logoutController.d.ts +8 -0
- package/dist/server/controllers/mock/logoutController.d.ts.map +1 -0
- package/dist/server/controllers/mock/logoutController.js +17 -0
- package/dist/server/controllers/mock/logoutController.js.map +1 -0
- package/dist/server/controllers/mock/navController.d.ts +8 -0
- package/dist/server/controllers/mock/navController.d.ts.map +1 -0
- package/dist/server/controllers/mock/navController.js +93 -0
- package/dist/server/controllers/mock/navController.js.map +1 -0
- package/dist/server/controllers/mock/tokenController.d.ts +8 -0
- package/dist/server/controllers/mock/tokenController.d.ts.map +1 -0
- package/dist/server/controllers/mock/tokenController.js +89 -0
- package/dist/server/controllers/mock/tokenController.js.map +1 -0
- 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/mock/mockConfig.d.ts +2 -4
- package/dist/server/mock/mockConfig.d.ts.map +1 -1
- package/dist/server/mock/mockConfig.js +11 -20
- package/dist/server/mock/mockConfig.js.map +1 -1
- package/dist/server/mock/mockRoutes.d.ts +13 -3
- package/dist/server/mock/mockRoutes.d.ts.map +1 -1
- package/dist/server/mock/mockRoutes.js +23 -85
- package/dist/server/mock/mockRoutes.js.map +1 -1
- package/dist/server/models/blacklistModel.js +2 -2
- package/dist/server/models/jwksModel.js +2 -2
- package/dist/server/routes.d.ts +1 -2
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +21 -29
- package/dist/server/routes.js.map +1 -1
- 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/mock/mockApiRoutes.d.ts +0 -14
- package/dist/server/mock/mockApiRoutes.d.ts.map +0 -1
- package/dist/server/mock/mockApiRoutes.js +0 -149
- package/dist/server/mock/mockApiRoutes.js.map +0 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockConfig.js","sourceRoot":"","sources":["../../../server/mock/mockConfig.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;
|
|
1
|
+
{"version":3,"file":"mockConfig.js","sourceRoot":"","sources":["../../../server/mock/mockConfig.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAkBH,gCAEC;AAMD,sCAUC;AAtBD;;;GAGG;AACH,SAAgB,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,MAAM,CAAA;AAC1C,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa;IAC3B,OAAO;QACL,OAAO,EAAE,UAAU,EAAE;QACrB,IAAI,EAAE;YACJ,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,eAAe;YACzD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO;YACnD,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE;YAC1D,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,GAAG,EAAE,EAAE,CAAC;SACzE;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mock OAuth
|
|
2
|
+
* Mock OAuth 路由
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* PUT /token
|
|
4
|
+
* 始终注册,非 mock 模式下所有处理器调用 next() 透传到真实路由。
|
|
5
|
+
* PUT /token 在 mock 模式下响应中携带 isMock: true,web SDK 据此走纯前端 mock 路径。
|
|
6
|
+
*
|
|
7
|
+
* Mock API 路由(挂载到 /mock)
|
|
8
|
+
*
|
|
9
|
+
* mock 模式下提供给 web SDK 直接调用的接口,无需页面跳转。
|
|
10
|
+
*
|
|
11
|
+
* 路由列表:
|
|
12
|
+
* POST /mock/login - 签发 mock token,返回用户信息
|
|
13
|
+
* POST /mock/logout - 清除 mock token cookie
|
|
14
|
+
* GET /mock/avatar/:id - 返回 404(mock 模式无头像服务)
|
|
15
|
+
* GET /mock/nav/:target - 导航占位页(home/site/user/feedback)
|
|
6
16
|
*/
|
|
7
17
|
declare const mockRoutes: import("express-serve-static-core").Router;
|
|
8
18
|
export default mockRoutes;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockRoutes.d.ts","sourceRoot":"","sources":["../../../server/mock/mockRoutes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mockRoutes.d.ts","sourceRoot":"","sources":["../../../server/mock/mockRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,QAAA,MAAM,UAAU,4CAAmB,CAAA;AASnC,eAAe,UAAU,CAAA"}
|
|
@@ -1,97 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Mock OAuth
|
|
3
|
+
* Mock OAuth 路由
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* PUT /token
|
|
5
|
+
* 始终注册,非 mock 模式下所有处理器调用 next() 透传到真实路由。
|
|
6
|
+
* PUT /token 在 mock 模式下响应中携带 isMock: true,web SDK 据此走纯前端 mock 路径。
|
|
7
|
+
*
|
|
8
|
+
* Mock API 路由(挂载到 /mock)
|
|
9
|
+
*
|
|
10
|
+
* mock 模式下提供给 web SDK 直接调用的接口,无需页面跳转。
|
|
11
|
+
*
|
|
12
|
+
* 路由列表:
|
|
13
|
+
* POST /mock/login - 签发 mock token,返回用户信息
|
|
14
|
+
* POST /mock/logout - 清除 mock token cookie
|
|
15
|
+
* GET /mock/avatar/:id - 返回 404(mock 模式无头像服务)
|
|
16
|
+
* GET /mock/nav/:target - 导航占位页(home/site/user/feedback)
|
|
7
17
|
*/
|
|
8
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
20
|
};
|
|
11
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
22
|
const express_1 = __importDefault(require("express"));
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
23
|
+
const tokenController_1 = require("../controllers/mock/tokenController");
|
|
24
|
+
const loginController_1 = require("../controllers/mock/loginController");
|
|
25
|
+
const logoutController_1 = require("../controllers/mock/logoutController");
|
|
26
|
+
const avatarController_1 = require("../controllers/mock/avatarController");
|
|
27
|
+
const navController_1 = require("../controllers/mock/navController");
|
|
16
28
|
const mockRoutes = express_1.default.Router();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
mockRoutes.
|
|
22
|
-
const { user } = (0, mockConfig_1.getMockConfig)();
|
|
23
|
-
const cookies = parseCookies(req.headers.cookie);
|
|
24
|
-
const accessTokenRaw = cookies.access_token || '';
|
|
25
|
-
const refreshTokenRaw = cookies.refresh_token || '';
|
|
26
|
-
// 先验证 access_token
|
|
27
|
-
if (accessTokenRaw && (0, mockTokenUtils_1.isMockToken)(accessTokenRaw)) {
|
|
28
|
-
try {
|
|
29
|
-
const claims = (0, mockTokenUtils_1.verifyMockToken)(accessTokenRaw);
|
|
30
|
-
if (claims.sub) {
|
|
31
|
-
return res.json({
|
|
32
|
-
code: 'OK',
|
|
33
|
-
message: 'Token 仍然有效',
|
|
34
|
-
data: {
|
|
35
|
-
isMock: true,
|
|
36
|
-
user: {
|
|
37
|
-
id: claims.sub,
|
|
38
|
-
isVerified: claims.isVerified ?? user.isVerified,
|
|
39
|
-
roles: claims.roles ?? user.roles,
|
|
40
|
-
permissions: claims.permissions ?? user.permissions
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// access_token 过期,继续尝试 refresh_token
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// 使用 refresh_token 重签 access_token
|
|
51
|
-
if (refreshTokenRaw && (0, mockTokenUtils_1.isMockToken)(refreshTokenRaw)) {
|
|
52
|
-
try {
|
|
53
|
-
(0, mockTokenUtils_1.verifyMockToken)(refreshTokenRaw);
|
|
54
|
-
const newAccessToken = (0, mockTokenUtils_1.generateMockAccessToken)(user);
|
|
55
|
-
(0, oauthTokenUtils_1.setOAuthTokenCookie)(res, newAccessToken, mockTokenUtils_1.MOCK_ACCESS_TOKEN_EXPIRES_IN, 'access');
|
|
56
|
-
return res.json({
|
|
57
|
-
code: 'OK',
|
|
58
|
-
message: 'Token 刷新成功',
|
|
59
|
-
data: {
|
|
60
|
-
isMock: true,
|
|
61
|
-
user: {
|
|
62
|
-
id: user.userId,
|
|
63
|
-
isVerified: user.isVerified,
|
|
64
|
-
roles: user.roles,
|
|
65
|
-
permissions: user.permissions
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
// refresh_token 也过期了
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// 未登录
|
|
75
|
-
return res.json({
|
|
76
|
-
code: 'OK',
|
|
77
|
-
message: '未登录',
|
|
78
|
-
data: {
|
|
79
|
-
isMock: true,
|
|
80
|
-
user: null
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
function parseCookies(cookieString) {
|
|
85
|
-
const cookies = {};
|
|
86
|
-
if (!cookieString)
|
|
87
|
-
return cookies;
|
|
88
|
-
cookieString.split(';').forEach(cookie => {
|
|
89
|
-
const [name, value] = cookie.split('=');
|
|
90
|
-
if (name && value) {
|
|
91
|
-
cookies[name.trim()] = value.trim();
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
return cookies;
|
|
95
|
-
}
|
|
29
|
+
mockRoutes.put('/token', tokenController_1.tokenController);
|
|
30
|
+
mockRoutes.post('/mock/login', loginController_1.loginController);
|
|
31
|
+
mockRoutes.post('/mock/logout', logoutController_1.logoutController);
|
|
32
|
+
mockRoutes.get('/mock/avatar/:id', avatarController_1.avatarController);
|
|
33
|
+
mockRoutes.get('/mock/nav/:target', navController_1.navController);
|
|
96
34
|
exports.default = mockRoutes;
|
|
97
35
|
//# sourceMappingURL=mockRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockRoutes.js","sourceRoot":"","sources":["../../../server/mock/mockRoutes.ts"],"names":[],"mappings":";AAAA;;;;;
|
|
1
|
+
{"version":3,"file":"mockRoutes.js","sourceRoot":"","sources":["../../../server/mock/mockRoutes.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;;;AAEH,sDAA6B;AAC7B,yEAAqE;AACrE,yEAAqE;AACrE,2EAAuE;AACvE,2EAAuE;AACvE,qEAAiE;AAEjE,MAAM,UAAU,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;AAEnC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,iCAAe,CAAC,CAAA;AAEzC,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,iCAAe,CAAC,CAAA;AAC/C,UAAU,CAAC,IAAI,CAAC,cAAc,EAAE,mCAAgB,CAAC,CAAA;AACjD,UAAU,CAAC,GAAG,CAAC,kBAAkB,EAAE,mCAAgB,CAAC,CAAA;AACpD,UAAU,CAAC,GAAG,CAAC,mBAAmB,EAAE,6BAAa,CAAC,CAAA;AAElD,kBAAe,UAAU,CAAA"}
|
|
@@ -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 中无可用的密钥');
|
package/dist/server/routes.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,QAAA,MAAM,WAAW,4CAAmB,CAAA;AA0BpC,eAAe,WAAW,CAAA"}
|
package/dist/server/routes.js
CHANGED
|
@@ -1,45 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Sumor OAuth 路由
|
|
4
|
-
*
|
|
5
|
-
* 当 OAUTH_MOCK=true 时,挂载 mock 路由替代真实 OAuth 流程
|
|
4
|
+
* 所有路由始终注册,在处理器内部根据 mock 模式决定具体行为。
|
|
6
5
|
*/
|
|
7
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
8
|
};
|
|
10
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
10
|
const express_1 = __importDefault(require("express"));
|
|
12
|
-
const mockConfig_1 = require("./mock/mockConfig");
|
|
13
11
|
const mockRoutes_1 = __importDefault(require("./mock/mockRoutes"));
|
|
14
|
-
const mockApiRoutes_1 = __importDefault(require("./mock/mockApiRoutes"));
|
|
15
12
|
const tokenRefreshController_1 = __importDefault(require("./controllers/tokenRefreshController"));
|
|
16
13
|
const oauthCallbackController_1 = __importDefault(require("./controllers/oauthCallbackController"));
|
|
17
14
|
const logoutController_1 = require("./controllers/logoutController");
|
|
18
15
|
const oauthRoutes = express_1.default.Router();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* 用户登出 - 需要有效的 Token
|
|
40
|
-
* POST /api/oauth/logout
|
|
41
|
-
*/
|
|
42
|
-
oauthRoutes.post('/logout', logoutController_1.logout);
|
|
43
|
-
}
|
|
16
|
+
/**
|
|
17
|
+
* Mock token 路由(PUT /token、GET /authorize 等)
|
|
18
|
+
* mock 模式下由 mockRoutes 处理,否则透传到后续真实路由
|
|
19
|
+
*/
|
|
20
|
+
oauthRoutes.use('/', mockRoutes_1.default);
|
|
21
|
+
/**
|
|
22
|
+
* Token 刷新端点
|
|
23
|
+
* PUT /token
|
|
24
|
+
*/
|
|
25
|
+
oauthRoutes.put('/token', tokenRefreshController_1.default);
|
|
26
|
+
/**
|
|
27
|
+
* OAuth 授权回调处理
|
|
28
|
+
* GET /callback
|
|
29
|
+
*/
|
|
30
|
+
oauthRoutes.get('/callback', oauthCallbackController_1.default);
|
|
31
|
+
/**
|
|
32
|
+
* 用户登出
|
|
33
|
+
* POST /logout
|
|
34
|
+
*/
|
|
35
|
+
oauthRoutes.post('/logout', logoutController_1.logout);
|
|
44
36
|
exports.default = oauthRoutes;
|
|
45
37
|
//# sourceMappingURL=routes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../server/routes.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;AAEH,sDAA6B;AAC7B,mEAA0C;AAC1C,kGAAyE;AACzE,oGAA2E;AAC3E,qEAAuD;AAEvD,MAAM,WAAW,GAAG,iBAAO,CAAC,MAAM,EAAE,CAAA;AAEpC;;;GAGG;AACH,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAU,CAAC,CAAA;AAEhC;;;GAGG;AACH,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,gCAAsB,CAAC,CAAA;AAEjD;;;GAGG;AACH,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,iCAAuB,CAAC,CAAA;AAErD;;;GAGG;AACH,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,yBAAM,CAAC,CAAA;AAEnC,kBAAe,WAAW,CAAA"}
|
|
@@ -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
|