@gooin/garmin-connect 1.7.3 → 1.7.5
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/dist/common/FileMFASessionStorage.d.ts +59 -0
- package/dist/common/FileMFASessionStorage.js +247 -0
- package/dist/common/FileMFASessionStorage.js.map +1 -0
- package/dist/common/HttpClient.js +7 -3
- package/dist/common/HttpClient.js.map +1 -1
- package/dist/common/MFAManager.d.ts +10 -14
- package/dist/common/MFAManager.js +49 -192
- package/dist/common/MFAManager.js.map +1 -1
- package/dist/common/MFASessionStorage.d.ts +42 -0
- package/dist/common/MFASessionStorage.js +3 -0
- package/dist/common/MFASessionStorage.js.map +1 -0
- package/dist/common/RedisMFASessionStorage.d.ts +60 -0
- package/dist/common/RedisMFASessionStorage.js +281 -0
- package/dist/common/RedisMFASessionStorage.js.map +1 -0
- package/dist/garmin/GarminConnect.d.ts +3 -2
- package/dist/garmin/GarminConnect.js +47 -7
- package/dist/garmin/GarminConnect.js.map +1 -1
- package/dist/garmin/UrlClass.d.ts +1 -0
- package/dist/garmin/UrlClass.js +3 -0
- package/dist/garmin/UrlClass.js.map +1 -1
- package/dist/garmin/types/index.d.ts +8 -0
- package/dist/garmin/types/index.js.map +1 -1
- package/package.json +5 -1
|
@@ -4,47 +4,57 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.MFAManager = void 0;
|
|
7
|
-
const
|
|
7
|
+
const FileMFASessionStorage_1 = require("./FileMFASessionStorage");
|
|
8
|
+
const RedisMFASessionStorage_1 = require("./RedisMFASessionStorage");
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
/**
|
|
10
11
|
* MFA管理器,用于处理需要等待外部验证码的登录流程
|
|
11
|
-
*
|
|
12
|
+
* 支持文件系统和Redis两种存储方式
|
|
12
13
|
*/
|
|
13
14
|
class MFAManager {
|
|
14
|
-
constructor(
|
|
15
|
+
constructor(config) {
|
|
15
16
|
this.DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5分钟
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
// 根据配置创建不同的存储实现
|
|
18
|
+
if (config.type === 'redis') {
|
|
19
|
+
if (config.redis) {
|
|
20
|
+
this.storage = new RedisMFASessionStorage_1.RedisMFASessionStorage(undefined, undefined, config.redis);
|
|
21
|
+
}
|
|
22
|
+
else if (config.redisUrl && config.redisToken) {
|
|
23
|
+
this.storage = new RedisMFASessionStorage_1.RedisMFASessionStorage(config.redisUrl, config.redisToken);
|
|
24
|
+
}
|
|
25
|
+
else if (config.redisUrl) {
|
|
26
|
+
this.storage = new RedisMFASessionStorage_1.RedisMFASessionStorage(config.redisUrl);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
throw new Error('Redis配置不完整,需要提供redisUrl或redis实例');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (config.type === 'file') {
|
|
33
|
+
const storageDir = config.dir || path_1.default.join(process.cwd(), '.mfa-sessions');
|
|
34
|
+
this.storage = new FileMFASessionStorage_1.FileMFASessionStorage(storageDir);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
throw new Error(`不支持的MFA存储类型: ${config.type}`);
|
|
38
|
+
}
|
|
20
39
|
}
|
|
21
40
|
/**
|
|
22
41
|
* 获取MFA管理器单例
|
|
23
42
|
*/
|
|
24
|
-
static getInstance(
|
|
43
|
+
static getInstance(config) {
|
|
25
44
|
if (!MFAManager.instance) {
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
if (!config) {
|
|
46
|
+
throw new Error('首次创建MFAManager实例必须提供配置');
|
|
47
|
+
}
|
|
48
|
+
console.log('创建MFA管理器实例', config);
|
|
49
|
+
MFAManager.instance = new MFAManager(config);
|
|
28
50
|
}
|
|
29
|
-
console.log('返回MFA管理器实例', MFAManager.instance.storageDir);
|
|
30
51
|
return MFAManager.instance;
|
|
31
52
|
}
|
|
32
53
|
/**
|
|
33
|
-
*
|
|
34
|
-
*/
|
|
35
|
-
async ensureStorageDir() {
|
|
36
|
-
try {
|
|
37
|
-
await fs_1.promises.mkdir(this.storageDir, { recursive: true });
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
console.error('创建MFA存储目录失败:', error);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* 获取会话文件路径
|
|
54
|
+
* 重置单例实例,用于测试或重新配置
|
|
45
55
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
static resetInstance() {
|
|
57
|
+
MFAManager.instance = undefined;
|
|
48
58
|
}
|
|
49
59
|
/**
|
|
50
60
|
* 创建一个等待MFA验证码的Promise
|
|
@@ -53,64 +63,7 @@ class MFAManager {
|
|
|
53
63
|
* @returns Promise<string> 返回验证码
|
|
54
64
|
*/
|
|
55
65
|
async waitForMFACode(sessionId, timeout = this.DEFAULT_TIMEOUT) {
|
|
56
|
-
|
|
57
|
-
await this.ensureStorageDir();
|
|
58
|
-
// 清理可能存在的旧会话
|
|
59
|
-
await this.cleanupRequest(sessionId);
|
|
60
|
-
// 创建会话文件
|
|
61
|
-
const sessionData = {
|
|
62
|
-
sessionId,
|
|
63
|
-
status: 'waiting',
|
|
64
|
-
createdAt: new Date().toISOString(),
|
|
65
|
-
timeout: timeout
|
|
66
|
-
};
|
|
67
|
-
const sessionFilePath = this.getSessionFilePath(sessionId);
|
|
68
|
-
await fs_1.promises.writeFile(sessionFilePath, JSON.stringify(sessionData), 'utf8');
|
|
69
|
-
console.log(`MFA验证会话已创建: ${sessionId}`);
|
|
70
|
-
// 轮询检查验证码是否已提交
|
|
71
|
-
return new Promise((resolve, reject) => {
|
|
72
|
-
const startTime = Date.now();
|
|
73
|
-
const checkInterval = setInterval(async () => {
|
|
74
|
-
try {
|
|
75
|
-
// 检查是否超时
|
|
76
|
-
if (Date.now() - startTime > timeout) {
|
|
77
|
-
clearInterval(checkInterval);
|
|
78
|
-
await this.cleanupRequest(sessionId);
|
|
79
|
-
reject(new Error('MFA验证超时,请重新登录'));
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
// 检查会话文件是否存在
|
|
83
|
-
try {
|
|
84
|
-
const data = await fs_1.promises.readFile(sessionFilePath, 'utf8');
|
|
85
|
-
const session = JSON.parse(data);
|
|
86
|
-
// 如果状态已更新为resolved,则返回验证码
|
|
87
|
-
if (session.status === 'resolved' && session.code) {
|
|
88
|
-
clearInterval(checkInterval);
|
|
89
|
-
await this.cleanupRequest(sessionId);
|
|
90
|
-
resolve(session.code);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
// 如果状态已更新为rejected,则抛出错误
|
|
94
|
-
if (session.status === 'rejected' && session.error) {
|
|
95
|
-
clearInterval(checkInterval);
|
|
96
|
-
await this.cleanupRequest(sessionId);
|
|
97
|
-
reject(new Error(session.error));
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
// 文件不存在或其他错误,继续等待
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
clearInterval(checkInterval);
|
|
107
|
-
await this.cleanupRequest(sessionId);
|
|
108
|
-
reject(error instanceof Error
|
|
109
|
-
? error
|
|
110
|
-
: new Error(String(error)));
|
|
111
|
-
}
|
|
112
|
-
}, 1000); // 每秒检查一次
|
|
113
|
-
});
|
|
66
|
+
return this.storage.waitForMFACode(sessionId, timeout);
|
|
114
67
|
}
|
|
115
68
|
/**
|
|
116
69
|
* 提交MFA验证码
|
|
@@ -119,27 +72,7 @@ class MFAManager {
|
|
|
119
72
|
* @returns 是否成功提交
|
|
120
73
|
*/
|
|
121
74
|
async submitMFACode(sessionId, code) {
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
// 检查会话文件是否存在
|
|
125
|
-
const data = await fs_1.promises.readFile(sessionFilePath, 'utf8');
|
|
126
|
-
const session = JSON.parse(data);
|
|
127
|
-
if (session.status !== 'waiting') {
|
|
128
|
-
console.log(`MFA验证会话状态不正确: ${sessionId}, 状态: ${session.status}`);
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
// 更新会话状态为已解决
|
|
132
|
-
session.status = 'resolved';
|
|
133
|
-
session.code = code;
|
|
134
|
-
session.resolvedAt = new Date().toISOString();
|
|
135
|
-
await fs_1.promises.writeFile(sessionFilePath, JSON.stringify(session), 'utf8');
|
|
136
|
-
console.log(`MFA验证码已提交: code ${code}, sessionId ${sessionId}`);
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
catch (error) {
|
|
140
|
-
console.log(`未找到MFA验证会话: ${sessionId}, 错误: ${error instanceof Error ? error.message : String(error)}`);
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
75
|
+
return this.storage.submitMFACode(sessionId, code);
|
|
143
76
|
}
|
|
144
77
|
/**
|
|
145
78
|
* 取消MFA验证
|
|
@@ -148,23 +81,7 @@ class MFAManager {
|
|
|
148
81
|
* @returns 是否成功取消
|
|
149
82
|
*/
|
|
150
83
|
async cancelMFARequest(sessionId, reason = 'MFA验证已取消') {
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
// 检查会话文件是否存在
|
|
154
|
-
const data = await fs_1.promises.readFile(sessionFilePath, 'utf8');
|
|
155
|
-
const session = JSON.parse(data);
|
|
156
|
-
// 更新会话状态为已拒绝
|
|
157
|
-
session.status = 'rejected';
|
|
158
|
-
session.error = reason;
|
|
159
|
-
session.rejectedAt = new Date().toISOString();
|
|
160
|
-
await fs_1.promises.writeFile(sessionFilePath, JSON.stringify(session), 'utf8');
|
|
161
|
-
console.log(`MFA验证已取消: ${sessionId}, 原因: ${reason}`);
|
|
162
|
-
return true;
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
console.log(`未找到MFA验证会话: ${sessionId}, 错误: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
84
|
+
return this.storage.cancelMFARequest(sessionId, reason);
|
|
168
85
|
}
|
|
169
86
|
/**
|
|
170
87
|
* 检查会话是否存在
|
|
@@ -172,89 +89,21 @@ class MFAManager {
|
|
|
172
89
|
* @returns 是否存在
|
|
173
90
|
*/
|
|
174
91
|
async hasSession(sessionId) {
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
await fs_1.promises.access(sessionFilePath);
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
catch (_a) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
92
|
+
return this.storage.hasSession(sessionId);
|
|
183
93
|
}
|
|
184
94
|
/**
|
|
185
95
|
* 获取所有活跃的会话ID
|
|
186
96
|
* @returns 会话ID列表
|
|
187
97
|
*/
|
|
188
98
|
async getActiveSessions() {
|
|
189
|
-
|
|
190
|
-
await this.ensureStorageDir();
|
|
191
|
-
const files = await fs_1.promises.readdir(this.storageDir);
|
|
192
|
-
return files
|
|
193
|
-
.filter((file) => file.endsWith('.json'))
|
|
194
|
-
.map((file) => file.replace('.json', ''));
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
console.error('获取活跃会话失败:', error instanceof Error ? error : String(error));
|
|
198
|
-
return [];
|
|
199
|
-
}
|
|
99
|
+
return this.storage.getActiveSessions();
|
|
200
100
|
}
|
|
201
101
|
/**
|
|
202
102
|
* 清理过期的请求
|
|
203
103
|
* @param maxAge 最大存活时间(毫秒)
|
|
204
104
|
*/
|
|
205
105
|
async cleanupExpiredRequests(maxAge = this.DEFAULT_TIMEOUT) {
|
|
206
|
-
|
|
207
|
-
await this.ensureStorageDir();
|
|
208
|
-
const files = await fs_1.promises.readdir(this.storageDir);
|
|
209
|
-
const now = new Date();
|
|
210
|
-
let cleanedCount = 0;
|
|
211
|
-
for (const file of files) {
|
|
212
|
-
if (!file.endsWith('.json'))
|
|
213
|
-
continue;
|
|
214
|
-
try {
|
|
215
|
-
const filePath = path_1.default.join(this.storageDir, file);
|
|
216
|
-
const data = await fs_1.promises.readFile(filePath, 'utf8');
|
|
217
|
-
const session = JSON.parse(data);
|
|
218
|
-
const createdAt = new Date(session.createdAt);
|
|
219
|
-
// 检查是否过期
|
|
220
|
-
if (now.getTime() - createdAt.getTime() > maxAge) {
|
|
221
|
-
await fs_1.promises.unlink(filePath);
|
|
222
|
-
cleanedCount++;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
// 如果文件读取失败,直接删除
|
|
227
|
-
try {
|
|
228
|
-
await fs_1.promises.unlink(path_1.default.join(this.storageDir, file));
|
|
229
|
-
cleanedCount++;
|
|
230
|
-
}
|
|
231
|
-
catch (unlinkError) {
|
|
232
|
-
console.error(`删除过期会话文件失败: ${file}`, unlinkError instanceof Error
|
|
233
|
-
? unlinkError
|
|
234
|
-
: String(unlinkError));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (cleanedCount > 0) {
|
|
239
|
-
console.log(`清理了 ${cleanedCount} 个过期的MFA验证会话`);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
console.error('清理过期请求失败:', error instanceof Error ? error : String(error));
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* 清理指定会话的资源
|
|
248
|
-
* @param sessionId 会话ID
|
|
249
|
-
*/
|
|
250
|
-
async cleanupRequest(sessionId) {
|
|
251
|
-
const sessionFilePath = this.getSessionFilePath(sessionId);
|
|
252
|
-
try {
|
|
253
|
-
await fs_1.promises.unlink(sessionFilePath);
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
// 文件不存在,忽略错误
|
|
257
|
-
}
|
|
106
|
+
return this.storage.cleanupExpiredRequests(maxAge);
|
|
258
107
|
}
|
|
259
108
|
/**
|
|
260
109
|
* 定期清理过期请求
|
|
@@ -264,6 +113,14 @@ class MFAManager {
|
|
|
264
113
|
this.cleanupExpiredRequests();
|
|
265
114
|
}, interval);
|
|
266
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* 关闭资源连接(主要用于Redis)
|
|
118
|
+
*/
|
|
119
|
+
async disconnect() {
|
|
120
|
+
if (this.storage instanceof RedisMFASessionStorage_1.RedisMFASessionStorage) {
|
|
121
|
+
await this.storage.disconnect();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
267
124
|
}
|
|
268
125
|
exports.MFAManager = MFAManager;
|
|
269
126
|
//# sourceMappingURL=MFAManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MFAManager.js","sourceRoot":"","sources":["../../src/common/MFAManager.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"MFAManager.js","sourceRoot":"","sources":["../../src/common/MFAManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MFA存储接口,定义了MFA会话存储的基本操作
|
|
3
|
+
*/
|
|
4
|
+
export interface MFASessionStorage {
|
|
5
|
+
/**
|
|
6
|
+
* 创建一个等待MFA验证码的会话
|
|
7
|
+
* @param sessionId 会话ID
|
|
8
|
+
* @param timeout 超时时间(毫秒)
|
|
9
|
+
* @returns Promise<string> 返回验证码
|
|
10
|
+
*/
|
|
11
|
+
waitForMFACode(sessionId: string, timeout?: number): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* 提交MFA验证码
|
|
14
|
+
* @param sessionId 会话ID
|
|
15
|
+
* @param code 验证码
|
|
16
|
+
* @returns 是否成功提交
|
|
17
|
+
*/
|
|
18
|
+
submitMFACode(sessionId: string, code: string): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* 取消MFA验证
|
|
21
|
+
* @param sessionId 会话ID
|
|
22
|
+
* @param reason 取消原因
|
|
23
|
+
* @returns 是否成功取消
|
|
24
|
+
*/
|
|
25
|
+
cancelMFARequest(sessionId: string, reason?: string): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* 检查会话是否存在
|
|
28
|
+
* @param sessionId 会话ID
|
|
29
|
+
* @returns 是否存在
|
|
30
|
+
*/
|
|
31
|
+
hasSession(sessionId: string): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* 获取所有活跃的会话ID
|
|
34
|
+
* @returns 会话ID列表
|
|
35
|
+
*/
|
|
36
|
+
getActiveSessions(): Promise<string[]>;
|
|
37
|
+
/**
|
|
38
|
+
* 清理过期的请求
|
|
39
|
+
* @param maxAge 最大存活时间(毫秒)
|
|
40
|
+
*/
|
|
41
|
+
cleanupExpiredRequests(maxAge?: number): Promise<void>;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MFASessionStorage.js","sourceRoot":"","sources":["../../src/common/MFASessionStorage.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { MFASessionStorage } from './MFASessionStorage';
|
|
2
|
+
/**
|
|
3
|
+
* Redis实现的MFA会话存储
|
|
4
|
+
*/
|
|
5
|
+
export declare class RedisMFASessionStorage implements MFASessionStorage {
|
|
6
|
+
private redis;
|
|
7
|
+
private readonly DEFAULT_TIMEOUT;
|
|
8
|
+
private readonly KEY_PREFIX;
|
|
9
|
+
constructor(redisUrl?: string, redisToken?: string, redisClient?: any);
|
|
10
|
+
/**
|
|
11
|
+
* 获取会话键名
|
|
12
|
+
*/
|
|
13
|
+
private getSessionKey;
|
|
14
|
+
/**
|
|
15
|
+
* 创建一个等待MFA验证码的Promise
|
|
16
|
+
* @param sessionId 会话ID
|
|
17
|
+
* @param timeout 超时时间(毫秒)
|
|
18
|
+
* @returns Promise<string> 返回验证码
|
|
19
|
+
*/
|
|
20
|
+
waitForMFACode(sessionId: string, timeout?: number): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* 提交MFA验证码
|
|
23
|
+
* @param sessionId 会话ID
|
|
24
|
+
* @param code 验证码
|
|
25
|
+
* @returns 是否成功提交
|
|
26
|
+
*/
|
|
27
|
+
submitMFACode(sessionId: string, code: string): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* 取消MFA验证
|
|
30
|
+
* @param sessionId 会话ID
|
|
31
|
+
* @param reason 取消原因
|
|
32
|
+
* @returns 是否成功取消
|
|
33
|
+
*/
|
|
34
|
+
cancelMFARequest(sessionId: string, reason?: string): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* 检查会话是否存在
|
|
37
|
+
* @param sessionId 会话ID
|
|
38
|
+
* @returns 是否存在
|
|
39
|
+
*/
|
|
40
|
+
hasSession(sessionId: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* 获取所有活跃的会话ID
|
|
43
|
+
* @returns 会话ID列表
|
|
44
|
+
*/
|
|
45
|
+
getActiveSessions(): Promise<string[]>;
|
|
46
|
+
/**
|
|
47
|
+
* 清理过期的请求
|
|
48
|
+
* @param maxAge 最大存活时间(毫秒)
|
|
49
|
+
*/
|
|
50
|
+
cleanupExpiredRequests(maxAge?: number): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* 清理指定会话的资源
|
|
53
|
+
* @param sessionId 会话ID
|
|
54
|
+
*/
|
|
55
|
+
private cleanupRequest;
|
|
56
|
+
/**
|
|
57
|
+
* 关闭Redis连接
|
|
58
|
+
*/
|
|
59
|
+
disconnect(): Promise<void>;
|
|
60
|
+
}
|