@shin1ohno/sage 0.8.8 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/cli/http-server-with-config.d.ts +2 -0
- package/dist/cli/http-server-with-config.d.ts.map +1 -1
- package/dist/cli/http-server-with-config.js +71 -0
- package/dist/cli/http-server-with-config.js.map +1 -1
- package/dist/cli/main-entry.d.ts.map +1 -1
- package/dist/cli/main-entry.js +1 -0
- package/dist/cli/main-entry.js.map +1 -1
- package/dist/cli/parser.d.ts +2 -0
- package/dist/cli/parser.d.ts.map +1 -1
- package/dist/cli/parser.js +7 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/config/validation.d.ts +721 -0
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +203 -0
- package/dist/config/validation.js.map +1 -1
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/integrations/apple-reminders.d.ts.map +1 -1
- package/dist/integrations/apple-reminders.js +6 -5
- package/dist/integrations/apple-reminders.js.map +1 -1
- package/dist/integrations/calendar-event-creator.d.ts.map +1 -1
- package/dist/integrations/calendar-event-creator.js +2 -1
- package/dist/integrations/calendar-event-creator.js.map +1 -1
- package/dist/integrations/calendar-event-deleter.d.ts.map +1 -1
- package/dist/integrations/calendar-event-deleter.js +2 -1
- package/dist/integrations/calendar-event-deleter.js.map +1 -1
- package/dist/integrations/calendar-event-response.d.ts.map +1 -1
- package/dist/integrations/calendar-event-response.js +4 -3
- package/dist/integrations/calendar-event-response.js.map +1 -1
- package/dist/integrations/calendar-service.d.ts +14 -0
- package/dist/integrations/calendar-service.d.ts.map +1 -1
- package/dist/integrations/calendar-service.js +6 -5
- package/dist/integrations/calendar-service.js.map +1 -1
- package/dist/integrations/calendar-source-manager.d.ts +86 -3
- package/dist/integrations/calendar-source-manager.d.ts.map +1 -1
- package/dist/integrations/calendar-source-manager.js +152 -20
- package/dist/integrations/calendar-source-manager.js.map +1 -1
- package/dist/integrations/google-calendar-service.d.ts +55 -3
- package/dist/integrations/google-calendar-service.d.ts.map +1 -1
- package/dist/integrations/google-calendar-service.js +215 -5
- package/dist/integrations/google-calendar-service.js.map +1 -1
- package/dist/integrations/notion-mcp.d.ts.map +1 -1
- package/dist/integrations/notion-mcp.js +5 -4
- package/dist/integrations/notion-mcp.js.map +1 -1
- package/dist/integrations/todo-list-manager.d.ts.map +1 -1
- package/dist/integrations/todo-list-manager.js +3 -2
- package/dist/integrations/todo-list-manager.js.map +1 -1
- package/dist/oauth/encryption-service.d.ts +104 -0
- package/dist/oauth/encryption-service.d.ts.map +1 -0
- package/dist/oauth/encryption-service.js +271 -0
- package/dist/oauth/encryption-service.js.map +1 -0
- package/dist/oauth/file-mutex.d.ts +68 -0
- package/dist/oauth/file-mutex.d.ts.map +1 -0
- package/dist/oauth/file-mutex.js +141 -0
- package/dist/oauth/file-mutex.js.map +1 -0
- package/dist/oauth/google-oauth-handler.d.ts +8 -9
- package/dist/oauth/google-oauth-handler.d.ts.map +1 -1
- package/dist/oauth/google-oauth-handler.js +30 -65
- package/dist/oauth/google-oauth-handler.js.map +1 -1
- package/dist/oauth/index.d.ts +1 -0
- package/dist/oauth/index.d.ts.map +1 -1
- package/dist/oauth/index.js +2 -0
- package/dist/oauth/index.js.map +1 -1
- package/dist/oauth/oauth-server.d.ts +61 -1
- package/dist/oauth/oauth-server.d.ts.map +1 -1
- package/dist/oauth/oauth-server.js +177 -40
- package/dist/oauth/oauth-server.js.map +1 -1
- package/dist/oauth/persistent-client-store.d.ts +58 -0
- package/dist/oauth/persistent-client-store.d.ts.map +1 -0
- package/dist/oauth/persistent-client-store.js +188 -0
- package/dist/oauth/persistent-client-store.js.map +1 -0
- package/dist/oauth/persistent-refresh-token-store.d.ts +77 -0
- package/dist/oauth/persistent-refresh-token-store.d.ts.map +1 -0
- package/dist/oauth/persistent-refresh-token-store.js +226 -0
- package/dist/oauth/persistent-refresh-token-store.js.map +1 -0
- package/dist/oauth/persistent-session-store.d.ts +69 -0
- package/dist/oauth/persistent-session-store.d.ts.map +1 -0
- package/dist/oauth/persistent-session-store.js +155 -0
- package/dist/oauth/persistent-session-store.js.map +1 -0
- package/dist/oauth/session-store.d.ts +31 -0
- package/dist/oauth/session-store.d.ts.map +1 -0
- package/dist/oauth/session-store.js +47 -0
- package/dist/oauth/session-store.js.map +1 -0
- package/dist/remote/cloud-config.d.ts.map +1 -1
- package/dist/remote/cloud-config.js +2 -1
- package/dist/remote/cloud-config.js.map +1 -1
- package/dist/services/container.d.ts.map +1 -1
- package/dist/services/container.js +3 -2
- package/dist/services/container.js.map +1 -1
- package/dist/services/working-cadence.d.ts +37 -1
- package/dist/services/working-cadence.d.ts.map +1 -1
- package/dist/services/working-cadence.js +152 -13
- package/dist/services/working-cadence.js.map +1 -1
- package/dist/tools/calendar/handlers.d.ts +82 -3
- package/dist/tools/calendar/handlers.d.ts.map +1 -1
- package/dist/tools/calendar/handlers.js +200 -16
- package/dist/tools/calendar/handlers.js.map +1 -1
- package/dist/types/google-calendar-types.d.ts +150 -3
- package/dist/types/google-calendar-types.d.ts.map +1 -1
- package/dist/types/google-calendar-types.js +79 -2
- package/dist/types/google-calendar-types.js.map +1 -1
- package/dist/types/task.d.ts +14 -0
- package/dist/types/task.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Mutex for Serializing File Operations
|
|
3
|
+
* Requirements: FR-1 (File Write Serialization), FR-2 (Per-File Mutex)
|
|
4
|
+
*
|
|
5
|
+
* Provides per-file mutex to prevent race conditions during concurrent
|
|
6
|
+
* encrypted file operations. Uses Promise queue pattern for serialization.
|
|
7
|
+
*/
|
|
8
|
+
import { resolve } from 'path';
|
|
9
|
+
import { oauthLogger } from '../utils/logger.js';
|
|
10
|
+
/**
|
|
11
|
+
* File Mutex Class
|
|
12
|
+
*
|
|
13
|
+
* Provides per-file locking mechanism to serialize file operations.
|
|
14
|
+
* Each file path gets its own independent mutex, allowing parallel
|
|
15
|
+
* operations on different files while serializing operations on the same file.
|
|
16
|
+
*/
|
|
17
|
+
export class FileMutex {
|
|
18
|
+
locks = new Map();
|
|
19
|
+
metrics = {
|
|
20
|
+
activeFiles: 0,
|
|
21
|
+
totalWaitTimeMs: 0,
|
|
22
|
+
longestWaitMs: 0,
|
|
23
|
+
queueDepthWarnings: 0,
|
|
24
|
+
};
|
|
25
|
+
// Thresholds for warnings
|
|
26
|
+
static QUEUE_DEPTH_WARNING_THRESHOLD = 10;
|
|
27
|
+
static WAIT_TIME_WARNING_THRESHOLD_MS = 5000;
|
|
28
|
+
/**
|
|
29
|
+
* Execute an operation with exclusive lock on the specified file
|
|
30
|
+
*
|
|
31
|
+
* @param filePath - Path to the file to lock
|
|
32
|
+
* @param operation - Async operation to execute while holding the lock
|
|
33
|
+
* @returns Result of the operation
|
|
34
|
+
*/
|
|
35
|
+
async withLock(filePath, operation) {
|
|
36
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
37
|
+
// Get or create mutex state for this file
|
|
38
|
+
if (!this.locks.has(normalizedPath)) {
|
|
39
|
+
this.locks.set(normalizedPath, { queue: [], isLocked: false });
|
|
40
|
+
this.metrics.activeFiles++;
|
|
41
|
+
}
|
|
42
|
+
const state = this.locks.get(normalizedPath);
|
|
43
|
+
// Wait if locked
|
|
44
|
+
if (state.isLocked) {
|
|
45
|
+
const queuedAt = Date.now();
|
|
46
|
+
await new Promise((resolvePromise) => {
|
|
47
|
+
state.queue.push({ resolve: resolvePromise, queuedAt });
|
|
48
|
+
this.checkQueueWarnings(normalizedPath, state);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Acquire lock
|
|
52
|
+
state.isLocked = true;
|
|
53
|
+
try {
|
|
54
|
+
return await operation();
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
// Release lock and notify next in queue
|
|
58
|
+
if (state.queue.length > 0) {
|
|
59
|
+
const next = state.queue.shift();
|
|
60
|
+
const waitTime = Date.now() - next.queuedAt;
|
|
61
|
+
this.recordWaitTime(waitTime, normalizedPath);
|
|
62
|
+
next.resolve();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
state.isLocked = false;
|
|
66
|
+
// Clean up empty mutex state
|
|
67
|
+
this.locks.delete(normalizedPath);
|
|
68
|
+
this.metrics.activeFiles = Math.max(0, this.metrics.activeFiles - 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Normalize file path for consistent lock identification
|
|
74
|
+
*/
|
|
75
|
+
normalizePath(filePath) {
|
|
76
|
+
return resolve(filePath);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check and warn if queue depth exceeds threshold
|
|
80
|
+
*/
|
|
81
|
+
checkQueueWarnings(filePath, state) {
|
|
82
|
+
if (state.queue.length >= FileMutex.QUEUE_DEPTH_WARNING_THRESHOLD) {
|
|
83
|
+
this.metrics.queueDepthWarnings++;
|
|
84
|
+
oauthLogger.warn({ filePath, queueLength: state.queue.length }, 'High mutex contention');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Record wait time and log if exceeds thresholds
|
|
89
|
+
*/
|
|
90
|
+
recordWaitTime(waitTimeMs, filePath) {
|
|
91
|
+
this.metrics.totalWaitTimeMs += waitTimeMs;
|
|
92
|
+
if (waitTimeMs > this.metrics.longestWaitMs) {
|
|
93
|
+
this.metrics.longestWaitMs = waitTimeMs;
|
|
94
|
+
}
|
|
95
|
+
// Log warnings for long wait times
|
|
96
|
+
if (waitTimeMs >= FileMutex.WAIT_TIME_WARNING_THRESHOLD_MS) {
|
|
97
|
+
oauthLogger.warn({ filePath, waitTimeMs }, 'Long mutex wait');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get metrics for monitoring/debugging
|
|
102
|
+
*/
|
|
103
|
+
getMetrics() {
|
|
104
|
+
return { ...this.metrics };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if there are pending operations for any file
|
|
108
|
+
*/
|
|
109
|
+
hasPendingOperations() {
|
|
110
|
+
for (const state of this.locks.values()) {
|
|
111
|
+
if (state.isLocked || state.queue.length > 0) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Wait for all pending operations to complete
|
|
119
|
+
*
|
|
120
|
+
* Used for graceful shutdown to ensure all queued operations finish.
|
|
121
|
+
*/
|
|
122
|
+
async waitForPending() {
|
|
123
|
+
// Keep checking until no more pending operations
|
|
124
|
+
while (this.hasPendingOperations()) {
|
|
125
|
+
// Wait a short time before checking again
|
|
126
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Reset metrics (primarily for testing)
|
|
131
|
+
*/
|
|
132
|
+
resetMetrics() {
|
|
133
|
+
this.metrics = {
|
|
134
|
+
activeFiles: this.locks.size,
|
|
135
|
+
totalWaitTimeMs: 0,
|
|
136
|
+
longestWaitMs: 0,
|
|
137
|
+
queueDepthWarnings: 0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=file-mutex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-mutex.js","sourceRoot":"","sources":["../../src/oauth/file-mutex.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,21 +36,20 @@ export declare const GOOGLE_CALENDAR_SCOPES: string[];
|
|
|
36
36
|
export declare class GoogleOAuthHandler {
|
|
37
37
|
private codeVerifier;
|
|
38
38
|
private config;
|
|
39
|
-
private readonly
|
|
39
|
+
private readonly encryptionService;
|
|
40
40
|
private readonly tokensStoragePath;
|
|
41
|
+
private initialized;
|
|
41
42
|
constructor(config: GoogleOAuthConfig, encryptionKey?: string, userId?: string);
|
|
42
43
|
/**
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Encrypt data using AES-256-GCM
|
|
44
|
+
* Initialize encryption service
|
|
45
|
+
*
|
|
46
|
+
* Must be called before any token storage operations.
|
|
48
47
|
*/
|
|
49
|
-
private
|
|
48
|
+
private ensureInitialized;
|
|
50
49
|
/**
|
|
51
|
-
*
|
|
50
|
+
* Create OAuth2Client instance
|
|
52
51
|
*/
|
|
53
|
-
private
|
|
52
|
+
private createOAuth2Client;
|
|
54
53
|
/**
|
|
55
54
|
* Generate authorization URL with PKCE code_challenge
|
|
56
55
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-oauth-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/google-oauth-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"google-oauth-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/google-oauth-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAYD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,UAGlC,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IACtD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,WAAW,CAAkB;gBAEzB,MAAM,EAAE,iBAAiB,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAY9E;;;;OAIG;YACW,iBAAiB;IAO/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;;;;;;OAQG;IACG,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBhE;;;;;;;;;;;OAWG;IACG,qBAAqB,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,iBAAiB,CAAC;IAqC7B;;;;;;OAMG;IACG,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA6B1E;;;;;OAKG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrD;;;;;;;OAOG;IACG,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB3D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA6BpD;;;;;;OAMG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BnC;;;;;;;;OAQG;IACG,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAShE;;;;;;;;;OASG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAgCzC;;;;;;;OAOG;IACH,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,YAAY;CAgBzD"}
|
|
@@ -7,12 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { google } from 'googleapis';
|
|
9
9
|
import { generateCodeVerifier, generateCodeChallenge } from './pkce.js';
|
|
10
|
-
import {
|
|
11
|
-
import { promisify } from 'util';
|
|
12
|
-
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
10
|
+
import { EncryptionService } from './encryption-service.js';
|
|
13
11
|
import { join } from 'path';
|
|
14
12
|
import { homedir } from 'os';
|
|
15
|
-
const scryptAsync = promisify(scrypt);
|
|
16
13
|
/**
|
|
17
14
|
* Google Calendar API Scopes
|
|
18
15
|
*/
|
|
@@ -29,65 +26,36 @@ export const GOOGLE_CALENDAR_SCOPES = [
|
|
|
29
26
|
export class GoogleOAuthHandler {
|
|
30
27
|
codeVerifier = null;
|
|
31
28
|
config;
|
|
32
|
-
|
|
29
|
+
encryptionService;
|
|
33
30
|
tokensStoragePath;
|
|
31
|
+
initialized = false;
|
|
34
32
|
constructor(config, encryptionKey, userId) {
|
|
35
33
|
this.config = config;
|
|
36
|
-
//
|
|
37
|
-
this.
|
|
34
|
+
// Initialize EncryptionService with provided key
|
|
35
|
+
this.encryptionService = new EncryptionService({
|
|
36
|
+
encryptionKey: encryptionKey || process.env.SAGE_ENCRYPTION_KEY,
|
|
37
|
+
});
|
|
38
38
|
// Store tokens at ~/.sage/google_oauth_tokens_{userId}.enc
|
|
39
39
|
const sageDir = join(homedir(), '.sage');
|
|
40
40
|
const userIdSuffix = userId ? `_${userId}` : '';
|
|
41
41
|
this.tokensStoragePath = join(sageDir, `google_oauth_tokens${userIdSuffix}.enc`);
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return new google.auth.OAuth2(this.config.clientId, this.config.clientSecret, redirectUri || this.config.redirectUri);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Encrypt data using AES-256-GCM
|
|
44
|
+
* Initialize encryption service
|
|
45
|
+
*
|
|
46
|
+
* Must be called before any token storage operations.
|
|
51
47
|
*/
|
|
52
|
-
async
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const iv = randomBytes(16);
|
|
58
|
-
// Create cipher
|
|
59
|
-
const cipher = createCipheriv('aes-256-gcm', key, iv);
|
|
60
|
-
// Encrypt data
|
|
61
|
-
let encrypted = cipher.update(data, 'utf8', 'hex');
|
|
62
|
-
encrypted += cipher.final('hex');
|
|
63
|
-
// Get auth tag
|
|
64
|
-
const authTag = cipher.getAuthTag();
|
|
65
|
-
// Combine: salt:iv:authTag:encrypted
|
|
66
|
-
return `${salt.toString('hex')}:${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
|
|
48
|
+
async ensureInitialized() {
|
|
49
|
+
if (!this.initialized) {
|
|
50
|
+
await this.encryptionService.initialize();
|
|
51
|
+
this.initialized = true;
|
|
52
|
+
}
|
|
67
53
|
}
|
|
68
54
|
/**
|
|
69
|
-
*
|
|
55
|
+
* Create OAuth2Client instance
|
|
70
56
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const parts = encryptedData.split(':');
|
|
74
|
-
if (parts.length !== 4) {
|
|
75
|
-
throw new Error('Invalid encrypted data format');
|
|
76
|
-
}
|
|
77
|
-
const [saltHex, ivHex, authTagHex, encrypted] = parts;
|
|
78
|
-
// Convert from hex
|
|
79
|
-
const salt = Buffer.from(saltHex, 'hex');
|
|
80
|
-
const iv = Buffer.from(ivHex, 'hex');
|
|
81
|
-
const authTag = Buffer.from(authTagHex, 'hex');
|
|
82
|
-
// Derive key from encryption key using scrypt
|
|
83
|
-
const key = (await scryptAsync(this.encryptionKey, salt, 32));
|
|
84
|
-
// Create decipher
|
|
85
|
-
const decipher = createDecipheriv('aes-256-gcm', key, iv);
|
|
86
|
-
decipher.setAuthTag(authTag);
|
|
87
|
-
// Decrypt data
|
|
88
|
-
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
89
|
-
decrypted += decipher.final('utf8');
|
|
90
|
-
return decrypted;
|
|
57
|
+
createOAuth2Client(redirectUri) {
|
|
58
|
+
return new google.auth.OAuth2(this.config.clientId, this.config.clientSecret, redirectUri || this.config.redirectUri);
|
|
91
59
|
}
|
|
92
60
|
/**
|
|
93
61
|
* Generate authorization URL with PKCE code_challenge
|
|
@@ -211,6 +179,8 @@ export class GoogleOAuthHandler {
|
|
|
211
179
|
*/
|
|
212
180
|
async storeTokens(tokens) {
|
|
213
181
|
try {
|
|
182
|
+
// Ensure encryption service is initialized
|
|
183
|
+
await this.ensureInitialized();
|
|
214
184
|
// Convert to stored format
|
|
215
185
|
const storedTokens = {
|
|
216
186
|
accessToken: tokens.accessToken,
|
|
@@ -218,14 +188,9 @@ export class GoogleOAuthHandler {
|
|
|
218
188
|
expiresAt: new Date(tokens.expiresAt).toISOString(),
|
|
219
189
|
scope: tokens.scope,
|
|
220
190
|
};
|
|
221
|
-
// Encrypt tokens
|
|
191
|
+
// Encrypt and store tokens using EncryptionService
|
|
222
192
|
const tokensJson = JSON.stringify(storedTokens);
|
|
223
|
-
|
|
224
|
-
// Ensure ~/.sage directory exists
|
|
225
|
-
const sageDir = join(homedir(), '.sage');
|
|
226
|
-
await mkdir(sageDir, { recursive: true });
|
|
227
|
-
// Write encrypted tokens to file
|
|
228
|
-
await writeFile(this.tokensStoragePath, encrypted, 'utf8');
|
|
193
|
+
await this.encryptionService.encryptToFile(tokensJson, this.tokensStoragePath);
|
|
229
194
|
}
|
|
230
195
|
catch (error) {
|
|
231
196
|
throw new Error(`Failed to store tokens: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
@@ -241,10 +206,14 @@ export class GoogleOAuthHandler {
|
|
|
241
206
|
*/
|
|
242
207
|
async getTokens() {
|
|
243
208
|
try {
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
// Decrypt tokens
|
|
247
|
-
const tokensJson = await this.
|
|
209
|
+
// Ensure encryption service is initialized
|
|
210
|
+
await this.ensureInitialized();
|
|
211
|
+
// Decrypt tokens from file using EncryptionService
|
|
212
|
+
const tokensJson = await this.encryptionService.decryptFromFile(this.tokensStoragePath);
|
|
213
|
+
// Return null if file not found
|
|
214
|
+
if (tokensJson === null) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
248
217
|
const storedTokens = JSON.parse(tokensJson);
|
|
249
218
|
// Convert to GoogleOAuthTokens format
|
|
250
219
|
return {
|
|
@@ -255,10 +224,6 @@ export class GoogleOAuthHandler {
|
|
|
255
224
|
};
|
|
256
225
|
}
|
|
257
226
|
catch (error) {
|
|
258
|
-
// Return null if file not found (user hasn't authenticated yet)
|
|
259
|
-
if (error.code === 'ENOENT') {
|
|
260
|
-
return null;
|
|
261
|
-
}
|
|
262
227
|
throw new Error(`Failed to get tokens: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
263
228
|
}
|
|
264
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-oauth-handler.js","sourceRoot":"","sources":["../../src/oauth/google-oauth-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"google-oauth-handler.js","sourceRoot":"","sources":["../../src/oauth/google-oauth-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/index.d.ts
CHANGED
|
@@ -10,4 +10,5 @@ export { createRefreshTokenStore, RefreshTokenStore } from './refresh-token-stor
|
|
|
10
10
|
export { createClientStore, ClientStore } from './client-store.js';
|
|
11
11
|
export { OAuthServer, createOAuthServer, OAuthServerConfig } from './oauth-server.js';
|
|
12
12
|
export { OAuthHandler, createOAuthHandler, OAuthHandlerConfig } from './oauth-handler.js';
|
|
13
|
+
export { FileMutex, FileMutexMetrics } from './file-mutex.js';
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGxI,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvF,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGvF,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAGxI,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvF,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGvF,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtF,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG1F,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/oauth/index.js
CHANGED
|
@@ -18,4 +18,6 @@ export { createClientStore } from './client-store.js';
|
|
|
18
18
|
export { OAuthServer, createOAuthServer } from './oauth-server.js';
|
|
19
19
|
// OAuth Handler
|
|
20
20
|
export { OAuthHandler, createOAuthHandler } from './oauth-handler.js';
|
|
21
|
+
// File Mutex (for serializing file operations)
|
|
22
|
+
export { FileMutex } from './file-mutex.js';
|
|
21
23
|
//# sourceMappingURL=index.js.map
|
package/dist/oauth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,OAAO;AACP,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAExI,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAgB,MAAM,oBAAoB,CAAC;AAEvF,2BAA2B;AAC3B,OAAO,EAAE,4BAA4B,EAA0B,MAAM,iBAAiB,CAAC;AAEvF,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAqB,MAAM,0BAA0B,CAAC;AAEtF,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAe,MAAM,mBAAmB,CAAC;AAEnE,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AAEtF,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAsB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/oauth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,OAAO;AACP,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAExI,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAgB,MAAM,oBAAoB,CAAC;AAEvF,2BAA2B;AAC3B,OAAO,EAAE,4BAA4B,EAA0B,MAAM,iBAAiB,CAAC;AAEvF,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAqB,MAAM,0BAA0B,CAAC;AAEtF,eAAe;AACf,OAAO,EAAE,iBAAiB,EAAe,MAAM,mBAAmB,CAAC;AAEnE,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AAEtF,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAsB,MAAM,oBAAoB,CAAC;AAE1F,+CAA+C;AAC/C,OAAO,EAAE,SAAS,EAAoB,MAAM,iBAAiB,CAAC"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { AuthorizationServerMetadata, ProtectedResourceMetadata, AuthorizationRequest, TokenResponse, OAuthError, OAuthClient, ClientRegistrationRequest, VerifyTokenResult, OAuthUser, UserSession } from './types.js';
|
|
8
8
|
import { ClientRegistrationResult } from './client-store.js';
|
|
9
|
+
import { EncryptionService } from './encryption-service.js';
|
|
9
10
|
/**
|
|
10
11
|
* OAuth Server Configuration
|
|
11
12
|
*/
|
|
@@ -18,6 +19,9 @@ export interface OAuthServerConfig {
|
|
|
18
19
|
users?: OAuthUser[];
|
|
19
20
|
privateKey?: string;
|
|
20
21
|
publicKey?: string;
|
|
22
|
+
enablePersistence?: boolean;
|
|
23
|
+
encryptionService?: EncryptionService;
|
|
24
|
+
storageBasePath?: string;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* Authorization Pending Request (stored during consent flow)
|
|
@@ -40,6 +44,7 @@ export declare class OAuthServer {
|
|
|
40
44
|
private users;
|
|
41
45
|
private pendingAuthRequests;
|
|
42
46
|
private loginAttempts;
|
|
47
|
+
private encryptionService?;
|
|
43
48
|
private privateKey;
|
|
44
49
|
private publicKey;
|
|
45
50
|
constructor(config: OAuthServerConfig, keys?: {
|
|
@@ -47,9 +52,17 @@ export declare class OAuthServer {
|
|
|
47
52
|
publicKey: string;
|
|
48
53
|
});
|
|
49
54
|
/**
|
|
50
|
-
* Initialize the server with generated keys
|
|
55
|
+
* Initialize the server with generated keys and load persisted data
|
|
51
56
|
*/
|
|
52
57
|
initialize(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Log startup metrics
|
|
60
|
+
*/
|
|
61
|
+
private logStartupMetrics;
|
|
62
|
+
/**
|
|
63
|
+
* Type guard to check if object has a method
|
|
64
|
+
*/
|
|
65
|
+
private hasMethod;
|
|
53
66
|
private parseExpiryToSeconds;
|
|
54
67
|
/**
|
|
55
68
|
* Get Protected Resource Metadata (RFC 9728)
|
|
@@ -156,6 +169,53 @@ export declare class OAuthServer {
|
|
|
156
169
|
scope: string;
|
|
157
170
|
description: string;
|
|
158
171
|
}>;
|
|
172
|
+
/**
|
|
173
|
+
* Shutdown the server and flush all pending data
|
|
174
|
+
*
|
|
175
|
+
* Call this method before server shutdown to ensure all data is persisted.
|
|
176
|
+
*/
|
|
177
|
+
shutdown(): Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Get metrics for monitoring
|
|
180
|
+
*/
|
|
181
|
+
getMetrics(): {
|
|
182
|
+
refreshTokens: {
|
|
183
|
+
count: number;
|
|
184
|
+
expiredCount: number;
|
|
185
|
+
rotatedCount: number;
|
|
186
|
+
};
|
|
187
|
+
clients: {
|
|
188
|
+
count: number;
|
|
189
|
+
};
|
|
190
|
+
sessions: {
|
|
191
|
+
count: number;
|
|
192
|
+
expiredCount: number;
|
|
193
|
+
};
|
|
194
|
+
storage?: {
|
|
195
|
+
tokensSize: number;
|
|
196
|
+
clientsSize: number;
|
|
197
|
+
sessionsSize: number;
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Get health status for monitoring
|
|
202
|
+
*/
|
|
203
|
+
getHealthStatus(): {
|
|
204
|
+
healthy: boolean;
|
|
205
|
+
encryption: {
|
|
206
|
+
initialized: boolean;
|
|
207
|
+
keySource: string;
|
|
208
|
+
};
|
|
209
|
+
storage: {
|
|
210
|
+
accessible: boolean;
|
|
211
|
+
lastSave?: string;
|
|
212
|
+
};
|
|
213
|
+
issues: string[];
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Get file size safely
|
|
217
|
+
*/
|
|
218
|
+
private getFileSize;
|
|
159
219
|
}
|
|
160
220
|
/**
|
|
161
221
|
* Create an OAuth Server instance
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-server.d.ts","sourceRoot":"","sources":["../../src/oauth/oauth-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"oauth-server.d.ts","sourceRoot":"","sources":["../../src/oauth/oauth-server.ts"],"names":[],"mappings":"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"}
|