@oxyhq/services 5.5.6 → 5.5.8
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/lib/commonjs/core/index.js +13 -13
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +467 -87
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAuthFetch.js +79 -29
- package/lib/commonjs/ui/hooks/useAuthFetch.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/core/index.js +13 -6
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +467 -87
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useAuthFetch.js +79 -29
- package/lib/module/ui/hooks/useAuthFetch.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/typescript/core/index.d.ts +7 -6
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +11 -7
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useAuthFetch.d.ts +10 -4
- package/lib/typescript/ui/hooks/useAuthFetch.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/backend-middleware.test.ts +209 -0
- package/src/__tests__/ui/hooks/useAuthFetch.test.ts +70 -0
- package/src/core/index.ts +13 -7
- package/src/ui/context/OxyContext.tsx +522 -99
- package/src/ui/hooks/useAuthFetch.ts +83 -29
- package/src/ui/screens/SessionManagementScreen.tsx +9 -9
- package/lib/commonjs/core/AuthManager.js +0 -352
- package/lib/commonjs/core/AuthManager.js.map +0 -1
- package/lib/module/core/AuthManager.js +0 -347
- package/lib/module/core/AuthManager.js.map +0 -1
- package/lib/typescript/core/AuthManager.d.ts +0 -100
- package/lib/typescript/core/AuthManager.d.ts.map +0 -1
- package/src/core/AuthManager.ts +0 -366
package/src/core/AuthManager.ts
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Centralized Authentication Manager
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for all authentication operations
|
|
5
|
-
* Handles both JWT and session-based authentication seamlessly
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { OxyServices } from './index';
|
|
9
|
-
|
|
10
|
-
export interface AuthState {
|
|
11
|
-
isAuthenticated: boolean;
|
|
12
|
-
accessToken: string | null;
|
|
13
|
-
user: any | null;
|
|
14
|
-
activeSessionId: string | null;
|
|
15
|
-
sessions: any[]; // For multi-session support
|
|
16
|
-
isLoading: boolean;
|
|
17
|
-
error: string | null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface AuthConfig {
|
|
21
|
-
oxyServices: OxyServices;
|
|
22
|
-
onStateChange?: (state: AuthState) => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export class AuthManager {
|
|
26
|
-
private oxyServices: OxyServices;
|
|
27
|
-
private onStateChange?: (state: AuthState) => void;
|
|
28
|
-
private currentState: AuthState = {
|
|
29
|
-
isAuthenticated: false,
|
|
30
|
-
accessToken: null,
|
|
31
|
-
user: null,
|
|
32
|
-
activeSessionId: null,
|
|
33
|
-
sessions: [],
|
|
34
|
-
isLoading: false,
|
|
35
|
-
error: null,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
constructor(config: AuthConfig) {
|
|
39
|
-
this.oxyServices = config.oxyServices;
|
|
40
|
-
this.onStateChange = config.onStateChange;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get current authentication state
|
|
45
|
-
*/
|
|
46
|
-
getState(): AuthState {
|
|
47
|
-
return { ...this.currentState };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get access token for API calls
|
|
52
|
-
* This is the ONLY method that should be used to get tokens
|
|
53
|
-
*/
|
|
54
|
-
async getAccessToken(): Promise<string | null> {
|
|
55
|
-
try {
|
|
56
|
-
// If we already have a valid JWT token, return it
|
|
57
|
-
let token = this.oxyServices.getAccessToken();
|
|
58
|
-
if (token) {
|
|
59
|
-
return token;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// If we have an active session, get token from session
|
|
63
|
-
if (this.currentState.activeSessionId) {
|
|
64
|
-
const tokenData = await this.oxyServices.getTokenBySession(this.currentState.activeSessionId);
|
|
65
|
-
token = tokenData.accessToken;
|
|
66
|
-
|
|
67
|
-
// Cache it for future calls
|
|
68
|
-
this.oxyServices.setTokens(token, '');
|
|
69
|
-
return token;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return null;
|
|
73
|
-
} catch (error) {
|
|
74
|
-
console.error('[AuthManager] Failed to get access token:', error);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Login with username/password
|
|
81
|
-
*/
|
|
82
|
-
async login(username: string, password: string, deviceName?: string): Promise<void> {
|
|
83
|
-
this.updateState({ isLoading: true, error: null });
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
// Use secure session login
|
|
87
|
-
const response = await this.oxyServices.secureLogin(username, password, deviceName);
|
|
88
|
-
|
|
89
|
-
// Get and cache the access token
|
|
90
|
-
const tokenData = await this.oxyServices.getTokenBySession(response.sessionId);
|
|
91
|
-
this.oxyServices.setTokens(tokenData.accessToken, '');
|
|
92
|
-
|
|
93
|
-
// Load full user data
|
|
94
|
-
const user = await this.oxyServices.getUserBySession(response.sessionId);
|
|
95
|
-
|
|
96
|
-
// Load sessions list
|
|
97
|
-
const sessions = await this.oxyServices.getSessionsBySessionId(response.sessionId);
|
|
98
|
-
|
|
99
|
-
this.updateState({
|
|
100
|
-
isAuthenticated: true,
|
|
101
|
-
accessToken: tokenData.accessToken,
|
|
102
|
-
user,
|
|
103
|
-
activeSessionId: response.sessionId,
|
|
104
|
-
sessions,
|
|
105
|
-
isLoading: false,
|
|
106
|
-
error: null,
|
|
107
|
-
});
|
|
108
|
-
} catch (error: any) {
|
|
109
|
-
this.updateState({
|
|
110
|
-
isLoading: false,
|
|
111
|
-
error: error.message || 'Login failed',
|
|
112
|
-
});
|
|
113
|
-
throw error;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Sign up new user
|
|
119
|
-
*/
|
|
120
|
-
async signUp(username: string, email: string, password: string): Promise<void> {
|
|
121
|
-
this.updateState({ isLoading: true, error: null });
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
// Create account
|
|
125
|
-
await this.oxyServices.signUp(username, email, password);
|
|
126
|
-
|
|
127
|
-
// Auto-login after signup
|
|
128
|
-
await this.login(username, password);
|
|
129
|
-
} catch (error: any) {
|
|
130
|
-
this.updateState({
|
|
131
|
-
isLoading: false,
|
|
132
|
-
error: error.message || 'Sign up failed',
|
|
133
|
-
});
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Logout current session or specific session
|
|
140
|
-
*/
|
|
141
|
-
async logout(targetSessionId?: string): Promise<void> {
|
|
142
|
-
if (!this.currentState.activeSessionId) return;
|
|
143
|
-
|
|
144
|
-
const sessionToLogout = targetSessionId || this.currentState.activeSessionId;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
await this.oxyServices.logoutSecureSession(
|
|
148
|
-
this.currentState.activeSessionId,
|
|
149
|
-
sessionToLogout
|
|
150
|
-
);
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.warn('[AuthManager] Logout API call failed:', error);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// If logging out current session, clear all state
|
|
156
|
-
if (sessionToLogout === this.currentState.activeSessionId) {
|
|
157
|
-
this.clearAuthState();
|
|
158
|
-
} else {
|
|
159
|
-
// Just remove the specific session from the list
|
|
160
|
-
const updatedSessions = this.currentState.sessions.filter(
|
|
161
|
-
(s: any) => s.sessionId !== sessionToLogout
|
|
162
|
-
);
|
|
163
|
-
this.updateState({ sessions: updatedSessions });
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Initialize authentication from stored data
|
|
169
|
-
*/
|
|
170
|
-
async initialize(activeSessionId: string | null): Promise<void> {
|
|
171
|
-
if (!activeSessionId) {
|
|
172
|
-
this.clearAuthState();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
this.updateState({ isLoading: true, error: null });
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
// Validate the session
|
|
180
|
-
const validation = await this.oxyServices.validateSession(activeSessionId);
|
|
181
|
-
|
|
182
|
-
if (!validation.valid) {
|
|
183
|
-
this.clearAuthState();
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Get access token
|
|
188
|
-
const tokenData = await this.oxyServices.getTokenBySession(activeSessionId);
|
|
189
|
-
this.oxyServices.setTokens(tokenData.accessToken, '');
|
|
190
|
-
|
|
191
|
-
// Load user data
|
|
192
|
-
const user = await this.oxyServices.getUserBySession(activeSessionId);
|
|
193
|
-
|
|
194
|
-
// Load sessions list
|
|
195
|
-
const sessions = await this.oxyServices.getSessionsBySessionId(activeSessionId);
|
|
196
|
-
|
|
197
|
-
this.updateState({
|
|
198
|
-
isAuthenticated: true,
|
|
199
|
-
accessToken: tokenData.accessToken,
|
|
200
|
-
user,
|
|
201
|
-
activeSessionId,
|
|
202
|
-
sessions,
|
|
203
|
-
isLoading: false,
|
|
204
|
-
error: null,
|
|
205
|
-
});
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.error('[AuthManager] Initialization failed:', error);
|
|
208
|
-
this.clearAuthState();
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Refresh current token
|
|
214
|
-
*/
|
|
215
|
-
async refreshToken(): Promise<void> {
|
|
216
|
-
if (!this.currentState.activeSessionId) {
|
|
217
|
-
throw new Error('No active session to refresh');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
const tokenData = await this.oxyServices.getTokenBySession(this.currentState.activeSessionId);
|
|
222
|
-
this.oxyServices.setTokens(tokenData.accessToken, '');
|
|
223
|
-
|
|
224
|
-
this.updateState({
|
|
225
|
-
accessToken: tokenData.accessToken,
|
|
226
|
-
});
|
|
227
|
-
} catch (error) {
|
|
228
|
-
console.error('[AuthManager] Token refresh failed:', error);
|
|
229
|
-
this.clearAuthState();
|
|
230
|
-
throw error;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Check if user is authenticated
|
|
236
|
-
*/
|
|
237
|
-
isAuthenticated(): boolean {
|
|
238
|
-
return this.currentState.isAuthenticated;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Get current user
|
|
243
|
-
*/
|
|
244
|
-
getCurrentUser(): any | null {
|
|
245
|
-
return this.currentState.user;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Get current session ID
|
|
250
|
-
*/
|
|
251
|
-
getActiveSessionId(): string | null {
|
|
252
|
-
return this.currentState.activeSessionId;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Get base URL for API calls
|
|
257
|
-
*/
|
|
258
|
-
getBaseURL(): string {
|
|
259
|
-
return this.oxyServices.getBaseURL();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Refresh sessions list
|
|
264
|
-
*/
|
|
265
|
-
async refreshSessions(): Promise<void> {
|
|
266
|
-
if (!this.currentState.activeSessionId) return;
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
const sessions = await this.oxyServices.getSessionsBySessionId(this.currentState.activeSessionId);
|
|
270
|
-
this.updateState({ sessions });
|
|
271
|
-
} catch (error) {
|
|
272
|
-
console.error('[AuthManager] Failed to refresh sessions:', error);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Get current sessions
|
|
278
|
-
*/
|
|
279
|
-
getSessions(): any[] {
|
|
280
|
-
return this.currentState.sessions;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Switch to a different session
|
|
285
|
-
*/
|
|
286
|
-
async switchSession(sessionId: string): Promise<void> {
|
|
287
|
-
if (sessionId === this.currentState.activeSessionId) return;
|
|
288
|
-
|
|
289
|
-
this.updateState({ isLoading: true, error: null });
|
|
290
|
-
|
|
291
|
-
try {
|
|
292
|
-
// Get access token for this session
|
|
293
|
-
const tokenData = await this.oxyServices.getTokenBySession(sessionId);
|
|
294
|
-
this.oxyServices.setTokens(tokenData.accessToken, '');
|
|
295
|
-
|
|
296
|
-
// Load user data
|
|
297
|
-
const user = await this.oxyServices.getUserBySession(sessionId);
|
|
298
|
-
|
|
299
|
-
this.updateState({
|
|
300
|
-
activeSessionId: sessionId,
|
|
301
|
-
accessToken: tokenData.accessToken,
|
|
302
|
-
user,
|
|
303
|
-
isLoading: false,
|
|
304
|
-
});
|
|
305
|
-
} catch (error) {
|
|
306
|
-
console.error('[AuthManager] Switch session failed:', error);
|
|
307
|
-
this.updateState({
|
|
308
|
-
isLoading: false,
|
|
309
|
-
error: 'Failed to switch session',
|
|
310
|
-
});
|
|
311
|
-
throw error;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Remove a session (alias for logout with sessionId)
|
|
317
|
-
*/
|
|
318
|
-
async removeSession(sessionId: string): Promise<void> {
|
|
319
|
-
await this.logout(sessionId);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Logout all sessions
|
|
324
|
-
*/
|
|
325
|
-
async logoutAll(): Promise<void> {
|
|
326
|
-
if (!this.currentState.activeSessionId) {
|
|
327
|
-
throw new Error('No active session found');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
try {
|
|
331
|
-
await this.oxyServices.logoutAllSecureSessions(this.currentState.activeSessionId);
|
|
332
|
-
this.clearAuthState();
|
|
333
|
-
} catch (error) {
|
|
334
|
-
console.error('[AuthManager] Logout all failed:', error);
|
|
335
|
-
throw error;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Clear authentication state
|
|
341
|
-
*/
|
|
342
|
-
private clearAuthState(): void {
|
|
343
|
-
this.oxyServices.setTokens('', ''); // Clear tokens from service
|
|
344
|
-
|
|
345
|
-
this.updateState({
|
|
346
|
-
isAuthenticated: false,
|
|
347
|
-
accessToken: null,
|
|
348
|
-
user: null,
|
|
349
|
-
activeSessionId: null,
|
|
350
|
-
sessions: [],
|
|
351
|
-
isLoading: false,
|
|
352
|
-
error: null,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Update state and notify listeners
|
|
358
|
-
*/
|
|
359
|
-
private updateState(updates: Partial<AuthState>): void {
|
|
360
|
-
this.currentState = { ...this.currentState, ...updates };
|
|
361
|
-
|
|
362
|
-
if (this.onStateChange) {
|
|
363
|
-
this.onStateChange(this.currentState);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|