@oxyhq/services 5.2.2 → 5.2.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.
Files changed (64) hide show
  1. package/lib/commonjs/core/index.js +117 -0
  2. package/lib/commonjs/core/index.js.map +1 -1
  3. package/lib/commonjs/models/secureSession.js +2 -0
  4. package/lib/commonjs/models/secureSession.js.map +1 -0
  5. package/lib/commonjs/ui/context/LegacyOxyContext.js +643 -0
  6. package/lib/commonjs/ui/context/LegacyOxyContext.js.map +1 -0
  7. package/lib/commonjs/ui/context/OxyContext.js +215 -450
  8. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  9. package/lib/commonjs/ui/context/SecureOxyContext.js +408 -0
  10. package/lib/commonjs/ui/context/SecureOxyContext.js.map +1 -0
  11. package/lib/commonjs/ui/screens/AccountCenterScreen.js +3 -3
  12. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  13. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +31 -30
  14. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  15. package/lib/commonjs/ui/screens/AppInfoScreen.js +4 -4
  16. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  17. package/lib/commonjs/ui/screens/SessionManagementScreen.js +34 -34
  18. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  19. package/lib/commonjs/ui/screens/SignInScreen.js +2 -2
  20. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  21. package/lib/module/core/index.js +117 -0
  22. package/lib/module/core/index.js.map +1 -1
  23. package/lib/module/models/secureSession.js +2 -0
  24. package/lib/module/models/secureSession.js.map +1 -0
  25. package/lib/module/ui/context/LegacyOxyContext.js +639 -0
  26. package/lib/module/ui/context/LegacyOxyContext.js.map +1 -0
  27. package/lib/module/ui/context/OxyContext.js +214 -450
  28. package/lib/module/ui/context/OxyContext.js.map +1 -1
  29. package/lib/module/ui/context/SecureOxyContext.js +403 -0
  30. package/lib/module/ui/context/SecureOxyContext.js.map +1 -0
  31. package/lib/module/ui/screens/AccountCenterScreen.js +3 -3
  32. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  33. package/lib/module/ui/screens/AccountSwitcherScreen.js +31 -30
  34. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  35. package/lib/module/ui/screens/AppInfoScreen.js +4 -4
  36. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  37. package/lib/module/ui/screens/SessionManagementScreen.js +34 -34
  38. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  39. package/lib/module/ui/screens/SignInScreen.js +2 -2
  40. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  41. package/lib/typescript/core/index.d.ts +51 -0
  42. package/lib/typescript/core/index.d.ts.map +1 -1
  43. package/lib/typescript/models/secureSession.d.ts +25 -0
  44. package/lib/typescript/models/secureSession.d.ts.map +1 -0
  45. package/lib/typescript/ui/context/LegacyOxyContext.d.ts +40 -0
  46. package/lib/typescript/ui/context/LegacyOxyContext.d.ts.map +1 -0
  47. package/lib/typescript/ui/context/OxyContext.d.ts +11 -12
  48. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  49. package/lib/typescript/ui/context/SecureOxyContext.d.ts +39 -0
  50. package/lib/typescript/ui/context/SecureOxyContext.d.ts.map +1 -0
  51. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  52. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/core/index.ts +117 -0
  55. package/src/index.ts +2 -2
  56. package/src/models/secureSession.ts +27 -0
  57. package/src/ui/context/LegacyOxyContext.tsx +735 -0
  58. package/src/ui/context/OxyContext.tsx +412 -674
  59. package/src/ui/context/SecureOxyContext.tsx +473 -0
  60. package/src/ui/screens/AccountCenterScreen.tsx +4 -4
  61. package/src/ui/screens/AccountSwitcherScreen.tsx +36 -34
  62. package/src/ui/screens/AppInfoScreen.tsx +3 -3
  63. package/src/ui/screens/SessionManagementScreen.tsx +31 -35
  64. package/src/ui/screens/SignInScreen.tsx +2 -2
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
4
-
5
- // Define authenticated user with tokens
3
+ import React, { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
6
4
 
7
5
  // Define the context shape
8
6
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -30,7 +28,6 @@ class WebStorage {
30
28
  }
31
29
 
32
30
  // React Native AsyncStorage implementation
33
- // This will be dynamically imported only in React Native environment
34
31
  let AsyncStorage;
35
32
 
36
33
  // Determine the platform and set up storage
@@ -41,7 +38,6 @@ const isReactNative = () => {
41
38
  // Get appropriate storage for the platform
42
39
  const getStorage = async () => {
43
40
  if (isReactNative()) {
44
- // Dynamically import AsyncStorage only in React Native environment
45
41
  if (!AsyncStorage) {
46
42
  try {
47
43
  const asyncStorageModule = await import('@react-native-async-storage/async-storage');
@@ -53,38 +49,33 @@ const getStorage = async () => {
53
49
  }
54
50
  return AsyncStorage;
55
51
  }
56
-
57
- // Default to web storage
58
52
  return new WebStorage();
59
53
  };
60
54
 
61
- // Storage keys
62
- const getStorageKeys = (prefix = 'oxy') => ({
63
- users: `${prefix}_users`,
64
- // Array of authenticated users with tokens
65
- activeUserId: `${prefix}_active_user_id`,
66
- // ID of currently active user
67
- // Legacy keys for migration
68
- accessToken: `${prefix}_access_token`,
69
- refreshToken: `${prefix}_refresh_token`,
70
- user: `${prefix}_user`
55
+ // Storage keys for secure sessions
56
+ const getSecureStorageKeys = (prefix = 'oxy_secure') => ({
57
+ sessions: `${prefix}_sessions`,
58
+ // Array of SecureClientSession objects
59
+ activeSessionId: `${prefix}_active_session_id` // ID of currently active session
71
60
  });
72
61
  export const OxyContextProvider = ({
73
62
  children,
74
63
  oxyServices,
75
- storageKeyPrefix = 'oxy',
64
+ storageKeyPrefix = 'oxy_secure',
76
65
  onAuthStateChange,
77
66
  bottomSheetRef
78
67
  }) => {
79
68
  // Authentication state
80
69
  const [user, setUser] = useState(null);
81
- const [users, setUsers] = useState([]);
70
+ const [minimalUser, setMinimalUser] = useState(null);
71
+ const [sessions, setSessions] = useState([]);
72
+ const [activeSessionId, setActiveSessionId] = useState(null);
82
73
  const [isLoading, setIsLoading] = useState(true);
83
74
  const [error, setError] = useState(null);
84
75
  const [storage, setStorage] = useState(null);
85
76
 
86
- // Storage keys
87
- const keys = getStorageKeys(storageKeyPrefix);
77
+ // Storage keys (memoized to prevent infinite loops)
78
+ const keys = useMemo(() => getSecureStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
88
79
 
89
80
  // Initialize storage
90
81
  useEffect(() => {
@@ -106,69 +97,54 @@ export const OxyContextProvider = ({
106
97
  if (!storage) return;
107
98
  setIsLoading(true);
108
99
  try {
109
- // Check for multi-user data first
110
- const usersData = await storage.getItem(keys.users);
111
- const activeUserId = await storage.getItem(keys.activeUserId);
112
- console.log('InitAuth - usersData:', usersData);
113
- console.log('InitAuth - activeUserId:', activeUserId);
114
- if (usersData) {
115
- // Multi-user setup exists
116
- const parsedUsers = JSON.parse(usersData);
117
- console.log('InitAuth - parsedUsers:', parsedUsers);
118
- setUsers(parsedUsers);
119
- if (activeUserId && parsedUsers.length > 0) {
120
- const activeUser = parsedUsers.find(u => u.id === activeUserId);
121
- console.log('InitAuth - activeUser found:', activeUser);
122
- if (activeUser) {
123
- setUser(activeUser);
124
- oxyServices.setTokens(activeUser.accessToken, activeUser.refreshToken || activeUser.accessToken);
125
-
126
- // Validate the tokens
127
- const isValid = await oxyServices.validate();
128
- console.log('InitAuth - token validation result:', isValid);
129
- if (!isValid) {
130
- // Remove invalid user during initialization
131
- console.log('InitAuth - removing invalid user due to failed validation');
132
- const filteredUsers = parsedUsers.filter(u => u.id !== activeUser.id);
133
- setUsers(filteredUsers);
134
- await saveUsersToStorage(filteredUsers);
135
-
136
- // If there are other users, switch to the first one
137
- if (filteredUsers.length > 0) {
138
- const newActiveUser = filteredUsers[0];
139
- setUser(newActiveUser);
140
- await saveActiveUserId(newActiveUser.id);
141
- oxyServices.setTokens(newActiveUser.accessToken, newActiveUser.refreshToken || newActiveUser.accessToken);
100
+ // Load stored sessions
101
+ const sessionsData = await storage.getItem(keys.sessions);
102
+ const storedActiveSessionId = await storage.getItem(keys.activeSessionId);
103
+ console.log('SecureAuth - sessionsData:', sessionsData);
104
+ console.log('SecureAuth - activeSessionId:', storedActiveSessionId);
105
+ if (sessionsData) {
106
+ const parsedSessions = JSON.parse(sessionsData);
107
+ setSessions(parsedSessions);
108
+ if (storedActiveSessionId && parsedSessions.length > 0) {
109
+ const activeSession = parsedSessions.find(s => s.sessionId === storedActiveSessionId);
110
+ if (activeSession) {
111
+ console.log('SecureAuth - activeSession found:', activeSession);
112
+
113
+ // Validate session
114
+ try {
115
+ const validation = await oxyServices.validateSession(activeSession.sessionId);
116
+ if (validation.valid) {
117
+ console.log('SecureAuth - session validated successfully');
118
+ setActiveSessionId(activeSession.sessionId);
119
+
120
+ // Get access token for API calls
121
+ await oxyServices.getTokenBySession(activeSession.sessionId);
122
+
123
+ // Load full user data
124
+ const fullUser = await oxyServices.getUserBySession(activeSession.sessionId);
125
+ setUser(fullUser);
126
+ setMinimalUser({
127
+ id: fullUser.id,
128
+ username: fullUser.username,
129
+ avatar: fullUser.avatar
130
+ });
142
131
  if (onAuthStateChange) {
143
- onAuthStateChange(newActiveUser);
132
+ onAuthStateChange(fullUser);
144
133
  }
145
134
  } else {
146
- // No valid users left
147
- setUser(null);
148
- await storage.removeItem(keys.activeUserId);
149
- oxyServices.clearTokens();
150
- if (onAuthStateChange) {
151
- onAuthStateChange(null);
152
- }
153
- }
154
- } else {
155
- console.log('InitAuth - user validated successfully, setting auth state');
156
- // Notify about auth state change
157
- if (onAuthStateChange) {
158
- onAuthStateChange(activeUser);
135
+ console.log('SecureAuth - session invalid, removing');
136
+ await removeInvalidSession(activeSession.sessionId);
159
137
  }
138
+ } catch (error) {
139
+ console.error('SecureAuth - session validation error:', error);
140
+ await removeInvalidSession(activeSession.sessionId);
160
141
  }
161
142
  }
162
143
  }
163
- } else {
164
- console.log('InitAuth - no users data, checking legacy auth');
165
- // Check for legacy single-user data and migrate
166
- await migrateLegacyAuth();
167
144
  }
168
145
  } catch (err) {
169
- console.error('Auth initialization error:', err);
146
+ console.error('Secure auth initialization error:', err);
170
147
  await clearAllStorage();
171
- oxyServices.clearTokens();
172
148
  } finally {
173
149
  setIsLoading(false);
174
150
  }
@@ -176,451 +152,238 @@ export const OxyContextProvider = ({
176
152
  if (storage) {
177
153
  initAuth();
178
154
  }
179
- }, [storage, oxyServices, keys.users, keys.activeUserId, onAuthStateChange]);
180
-
181
- // Migrate legacy single-user authentication to multi-user
182
- const migrateLegacyAuth = async () => {
183
- if (!storage) return;
184
- try {
185
- const accessToken = await storage.getItem(keys.accessToken);
186
- const refreshToken = await storage.getItem(keys.refreshToken);
187
- const storedUser = await storage.getItem(keys.user);
188
- if (accessToken && storedUser) {
189
- // Set tokens in OxyServices
190
- oxyServices.setTokens(accessToken, refreshToken || accessToken);
191
-
192
- // Validate the tokens
193
- const isValid = await oxyServices.validate();
194
- if (isValid) {
195
- const parsedUser = JSON.parse(storedUser);
196
- const authenticatedUser = {
197
- ...parsedUser,
198
- accessToken,
199
- refreshToken: refreshToken || undefined
200
- };
201
-
202
- // Store in new multi-user format
203
- await storage.setItem(keys.users, JSON.stringify([authenticatedUser]));
204
- await storage.setItem(keys.activeUserId, authenticatedUser.id);
205
-
206
- // Set state
207
- setUsers([authenticatedUser]);
208
- setUser(authenticatedUser);
209
-
210
- // Notify about auth state change
211
- if (onAuthStateChange) {
212
- onAuthStateChange(authenticatedUser);
213
- }
214
- }
215
-
216
- // Clear legacy storage
217
- await storage.removeItem(keys.accessToken);
218
- await storage.removeItem(keys.refreshToken);
219
- await storage.removeItem(keys.user);
155
+ }, [storage, oxyServices, keys, onAuthStateChange]);
156
+
157
+ // Remove invalid session
158
+ const removeInvalidSession = useCallback(async sessionId => {
159
+ const filteredSessions = sessions.filter(s => s.sessionId !== sessionId);
160
+ setSessions(filteredSessions);
161
+ await saveSessionsToStorage(filteredSessions);
162
+
163
+ // If there are other sessions, switch to the first one
164
+ if (filteredSessions.length > 0) {
165
+ await switchToSession(filteredSessions[0].sessionId);
166
+ } else {
167
+ // No valid sessions left
168
+ setActiveSessionId(null);
169
+ setUser(null);
170
+ setMinimalUser(null);
171
+ await storage?.removeItem(keys.activeSessionId);
172
+ if (onAuthStateChange) {
173
+ onAuthStateChange(null);
220
174
  }
221
- } catch (err) {
222
- console.error('Migration error:', err);
223
175
  }
224
- };
176
+ }, [sessions, storage, keys, onAuthStateChange]);
225
177
 
226
- // Helper to clear legacy storage
227
- const clearStorage = async () => {
178
+ // Save sessions to storage
179
+ const saveSessionsToStorage = useCallback(async sessionsList => {
228
180
  if (!storage) return;
229
- try {
230
- await storage.removeItem(keys.accessToken);
231
- await storage.removeItem(keys.refreshToken);
232
- await storage.removeItem(keys.user);
233
- } catch (err) {
234
- console.error('Clear storage error:', err);
235
- }
236
- };
181
+ await storage.setItem(keys.sessions, JSON.stringify(sessionsList));
182
+ }, [storage, keys.sessions]);
183
+
184
+ // Save active session ID to storage
185
+ const saveActiveSessionId = useCallback(async sessionId => {
186
+ if (!storage) return;
187
+ await storage.setItem(keys.activeSessionId, sessionId);
188
+ }, [storage, keys.activeSessionId]);
237
189
 
238
- // Helper to clear all storage (multi-user)
239
- const clearAllStorage = async () => {
190
+ // Clear all storage
191
+ const clearAllStorage = useCallback(async () => {
240
192
  if (!storage) return;
241
193
  try {
242
- await storage.removeItem(keys.users);
243
- await storage.removeItem(keys.activeUserId);
244
- // Also clear legacy keys
245
- await clearStorage();
194
+ await storage.removeItem(keys.sessions);
195
+ await storage.removeItem(keys.activeSessionId);
246
196
  } catch (err) {
247
- console.error('Clear all storage error:', err);
197
+ console.error('Clear secure storage error:', err);
248
198
  }
249
- };
250
-
251
- // Save users to storage
252
- const saveUsersToStorage = async usersList => {
253
- if (!storage) return;
254
- await storage.setItem(keys.users, JSON.stringify(usersList));
255
- };
199
+ }, [storage, keys]);
256
200
 
257
- // Save active user ID to storage
258
- const saveActiveUserId = async userId => {
259
- if (!storage) return;
260
- await storage.setItem(keys.activeUserId, userId);
261
- };
201
+ // Switch to a different session
202
+ const switchToSession = useCallback(async sessionId => {
203
+ try {
204
+ setIsLoading(true);
262
205
 
263
- // Utility function to handle different token response formats
264
- const storeTokens = async response => {
265
- // Store token and user data
266
- if (response.accessToken) {
267
- await storage?.setItem(keys.accessToken, response.accessToken);
268
- if (response.refreshToken) {
269
- await storage?.setItem(keys.refreshToken, response.refreshToken);
206
+ // Get access token for this session
207
+ await oxyServices.getTokenBySession(sessionId);
208
+
209
+ // Load full user data
210
+ const fullUser = await oxyServices.getUserBySession(sessionId);
211
+ setActiveSessionId(sessionId);
212
+ setUser(fullUser);
213
+ setMinimalUser({
214
+ id: fullUser.id,
215
+ username: fullUser.username,
216
+ avatar: fullUser.avatar
217
+ });
218
+ await saveActiveSessionId(sessionId);
219
+ if (onAuthStateChange) {
220
+ onAuthStateChange(fullUser);
270
221
  }
271
- } else if (response.token) {
272
- // Handle legacy API response
273
- await storage?.setItem(keys.accessToken, response.token);
222
+ } catch (error) {
223
+ console.error('Switch session error:', error);
224
+ setError('Failed to switch session');
225
+ } finally {
226
+ setIsLoading(false);
274
227
  }
275
- await storage?.setItem(keys.user, JSON.stringify(response.user));
276
- };
228
+ }, [oxyServices, onAuthStateChange, saveActiveSessionId]);
277
229
 
278
- // Login method (updated for multi-user)
279
- const login = async (username, password) => {
230
+ // Secure login method
231
+ const login = async (username, password, deviceName) => {
280
232
  if (!storage) throw new Error('Storage not initialized');
281
233
  setIsLoading(true);
282
234
  setError(null);
283
235
  try {
284
- const response = await oxyServices.login(username, password);
285
- const accessToken = response.accessToken || response.token;
286
- if (!accessToken) {
287
- throw new Error('No access token received from login');
288
- }
289
- const newUser = {
290
- ...response.user,
291
- accessToken,
292
- refreshToken: response.refreshToken
293
- // sessionId will be set by backend, but we don't get it in response yet
236
+ const response = await oxyServices.secureLogin(username, password, deviceName);
237
+
238
+ // Create client session object
239
+ const clientSession = {
240
+ sessionId: response.sessionId,
241
+ deviceId: response.deviceId,
242
+ expiresAt: response.expiresAt,
243
+ lastActive: new Date().toISOString()
294
244
  };
295
245
 
296
- // Check if user already exists
297
- const existingUserIndex = users.findIndex(u => u.id === newUser.id);
298
- let updatedUsers;
299
- if (existingUserIndex >= 0) {
300
- // Update existing user
301
- updatedUsers = [...users];
302
- updatedUsers[existingUserIndex] = newUser;
303
- } else {
304
- // Add new user
305
- updatedUsers = [...users, newUser];
306
- }
246
+ // Add to sessions list
247
+ const updatedSessions = [...sessions, clientSession];
248
+ setSessions(updatedSessions);
249
+ await saveSessionsToStorage(updatedSessions);
307
250
 
308
- // Update state
309
- setUsers(updatedUsers);
310
- setUser(newUser);
251
+ // Set as active session
252
+ setActiveSessionId(response.sessionId);
253
+ await saveActiveSessionId(response.sessionId);
311
254
 
312
- // Save to storage
313
- await saveUsersToStorage(updatedUsers);
314
- await saveActiveUserId(newUser.id);
255
+ // Get access token for API calls
256
+ await oxyServices.getTokenBySession(response.sessionId);
315
257
 
316
- // Notify about auth state change
258
+ // Load full user data
259
+ const fullUser = await oxyServices.getUserBySession(response.sessionId);
260
+ setUser(fullUser);
261
+ setMinimalUser(response.user);
317
262
  if (onAuthStateChange) {
318
- onAuthStateChange(newUser);
263
+ onAuthStateChange(fullUser);
319
264
  }
320
- return newUser;
321
- } catch (err) {
322
- setError(err.message || 'Login failed');
323
- throw err;
265
+ return fullUser;
266
+ } catch (error) {
267
+ setError(error.message || 'Login failed');
268
+ throw error;
324
269
  } finally {
325
270
  setIsLoading(false);
326
271
  }
327
272
  };
328
273
 
329
- // Logout method (supports multi-user)
330
- const logout = async userId => {
331
- if (!storage) throw new Error('Storage not initialized');
332
- setIsLoading(true);
333
- setError(null);
274
+ // Logout method
275
+ const logout = async targetSessionId => {
276
+ if (!activeSessionId) return;
334
277
  try {
335
- const targetUserId = userId || user?.id;
336
- if (!targetUserId) return;
337
- const targetUser = users.find(u => u.id === targetUserId);
338
- if (targetUser) {
339
- // Set the target user's tokens to logout
340
- oxyServices.setTokens(targetUser.accessToken, targetUser.refreshToken || targetUser.accessToken);
341
- try {
342
- await oxyServices.logout();
343
- } catch (logoutError) {
344
- console.warn('Logout API call failed:', logoutError);
345
- }
346
-
347
- // Remove user from list
348
- const updatedUsers = users.filter(u => u.id !== targetUserId);
349
- setUsers(updatedUsers);
350
-
351
- // If logging out current user, switch to another user or clear
352
- if (targetUserId === user?.id) {
353
- if (updatedUsers.length > 0) {
354
- // Switch to first available user
355
- const nextUser = updatedUsers[0];
356
- setUser(nextUser);
357
- oxyServices.setTokens(nextUser.accessToken, nextUser.refreshToken || nextUser.accessToken);
358
- await saveActiveUserId(nextUser.id);
359
- if (onAuthStateChange) {
360
- onAuthStateChange(nextUser);
361
- }
362
- } else {
363
- // No users left
364
- setUser(null);
365
- oxyServices.clearTokens();
366
- await storage.removeItem(keys.activeUserId);
367
- if (onAuthStateChange) {
368
- onAuthStateChange(null);
369
- }
278
+ const sessionToLogout = targetSessionId || activeSessionId;
279
+ await oxyServices.logoutSecureSession(activeSessionId, sessionToLogout);
280
+
281
+ // Remove session from local storage
282
+ const filteredSessions = sessions.filter(s => s.sessionId !== sessionToLogout);
283
+ setSessions(filteredSessions);
284
+ await saveSessionsToStorage(filteredSessions);
285
+
286
+ // If logging out active session
287
+ if (sessionToLogout === activeSessionId) {
288
+ if (filteredSessions.length > 0) {
289
+ // Switch to another session
290
+ await switchToSession(filteredSessions[0].sessionId);
291
+ } else {
292
+ // No sessions left
293
+ setActiveSessionId(null);
294
+ setUser(null);
295
+ setMinimalUser(null);
296
+ await storage?.removeItem(keys.activeSessionId);
297
+ if (onAuthStateChange) {
298
+ onAuthStateChange(null);
370
299
  }
371
300
  }
372
-
373
- // Save updated users list
374
- await saveUsersToStorage(updatedUsers);
375
301
  }
376
- } catch (err) {
377
- setError(err.message || 'Logout failed');
378
- throw err;
379
- } finally {
380
- setIsLoading(false);
302
+ } catch (error) {
303
+ console.error('Logout error:', error);
304
+ setError('Logout failed');
381
305
  }
382
306
  };
383
307
 
384
- // Logout all users
308
+ // Logout all sessions
385
309
  const logoutAll = async () => {
386
- if (!storage) throw new Error('Storage not initialized');
387
- setIsLoading(true);
388
- setError(null);
310
+ if (!activeSessionId) return;
389
311
  try {
390
- // Logout each user
391
- for (const userItem of users) {
392
- try {
393
- oxyServices.setTokens(userItem.accessToken, userItem.refreshToken || userItem.accessToken);
394
- await oxyServices.logout();
395
- } catch (logoutError) {
396
- console.warn(`Logout failed for user ${userItem.id}:`, logoutError);
397
- }
398
- }
312
+ await oxyServices.logoutAllSecureSessions(activeSessionId);
399
313
 
400
- // Clear all state and storage
401
- setUsers([]);
314
+ // Clear all local data
315
+ setSessions([]);
316
+ setActiveSessionId(null);
402
317
  setUser(null);
403
- oxyServices.clearTokens();
318
+ setMinimalUser(null);
404
319
  await clearAllStorage();
405
-
406
- // Notify about auth state change
407
320
  if (onAuthStateChange) {
408
321
  onAuthStateChange(null);
409
322
  }
410
- } catch (err) {
411
- setError(err.message || 'Logout all failed');
412
- throw err;
413
- } finally {
414
- setIsLoading(false);
415
- }
416
- };
417
-
418
- // Switch user
419
- const switchUser = async userId => {
420
- if (!storage) throw new Error('Storage not initialized');
421
- setError(null);
422
- try {
423
- const targetUser = users.find(u => u.id === userId);
424
- if (!targetUser) {
425
- throw new Error('User not found');
426
- }
427
-
428
- // Validate tokens before switching
429
- oxyServices.setTokens(targetUser.accessToken, targetUser.refreshToken || targetUser.accessToken);
430
- const isValid = await oxyServices.validate();
431
- if (!isValid) {
432
- // Remove invalid user
433
- await removeUser(userId);
434
- throw new Error('User session is invalid');
435
- }
436
-
437
- // Switch to the user
438
- setUser(targetUser);
439
- await saveActiveUserId(userId);
440
-
441
- // Notify about auth state change
442
- if (onAuthStateChange) {
443
- onAuthStateChange(targetUser);
444
- }
445
- } catch (err) {
446
- setError(err.message || 'Switch user failed');
447
- throw err;
323
+ } catch (error) {
324
+ console.error('Logout all error:', error);
325
+ setError('Logout all failed');
448
326
  }
449
327
  };
450
328
 
451
- // Remove user
452
- const removeUser = async userId => {
453
- if (!storage) throw new Error('Storage not initialized');
454
- try {
455
- const updatedUsers = users.filter(u => u.id !== userId);
456
- setUsers(updatedUsers);
457
-
458
- // If removing current user, switch to another or clear
459
- if (userId === user?.id) {
460
- if (updatedUsers.length > 0) {
461
- await switchUser(updatedUsers[0].id);
462
- } else {
463
- setUser(null);
464
- oxyServices.clearTokens();
465
- await storage.removeItem(keys.activeUserId);
466
- if (onAuthStateChange) {
467
- onAuthStateChange(null);
468
- }
469
- }
470
- }
471
-
472
- // Save updated users list
473
- await saveUsersToStorage(updatedUsers);
474
- } catch (err) {
475
- setError(err.message || 'Remove user failed');
476
- throw err;
477
- }
329
+ // Sign up method (placeholder - you can implement based on your needs)
330
+ const signUp = async (username, email, password) => {
331
+ // Implement sign up logic similar to secureLogin
332
+ throw new Error('Sign up not implemented yet');
478
333
  };
479
334
 
480
- // Get user sessions
481
- const getUserSessions = async userId => {
482
- try {
483
- const targetUserId = userId || user?.id;
484
- if (!targetUserId) return [];
485
- const targetUser = users.find(u => u.id === targetUserId);
486
- if (!targetUser) return [];
487
-
488
- // Store current tokens to restore later
489
- const currentUser = user;
490
- const wasCurrentUser = targetUserId === user?.id;
491
- if (!wasCurrentUser) {
492
- // Temporarily switch to target user's tokens
493
- oxyServices.setTokens(targetUser.accessToken, targetUser.refreshToken || targetUser.accessToken);
494
- }
495
- try {
496
- // Use the new OxyServices method
497
- const sessions = await oxyServices.getUserSessions();
498
- return sessions;
499
- } finally {
500
- if (!wasCurrentUser && currentUser) {
501
- // Restore original tokens
502
- oxyServices.setTokens(currentUser.accessToken, currentUser.refreshToken || currentUser.accessToken);
503
- }
504
- }
505
- } catch (err) {
506
- console.error('Get user sessions failed:', err);
507
- return [];
508
- }
335
+ // Switch session method
336
+ const switchSession = async sessionId => {
337
+ await switchToSession(sessionId);
509
338
  };
510
339
 
511
- // Logout specific session
512
- const logoutSession = async (sessionId, userId) => {
513
- try {
514
- const targetUserId = userId || user?.id;
515
- if (!targetUserId) return;
516
- const targetUser = users.find(u => u.id === targetUserId);
517
- if (!targetUser) return;
518
-
519
- // Store current tokens to restore later
520
- const currentUser = user;
521
- const wasCurrentUser = targetUserId === user?.id;
522
- if (!wasCurrentUser) {
523
- // Temporarily switch to target user's tokens
524
- oxyServices.setTokens(targetUser.accessToken, targetUser.refreshToken || targetUser.accessToken);
525
- }
526
- try {
527
- // Use the new OxyServices method
528
- await oxyServices.logoutSession(sessionId);
529
-
530
- // If this is the current user's session, remove them from local state
531
- if (wasCurrentUser && sessionId === targetUser.sessionId) {
532
- await removeUser(targetUserId);
533
- }
534
- } finally {
535
- if (!wasCurrentUser && currentUser) {
536
- // Restore original tokens
537
- oxyServices.setTokens(currentUser.accessToken, currentUser.refreshToken || currentUser.accessToken);
538
- }
539
- }
540
- } catch (err) {
541
- console.error('Logout session failed:', err);
542
- throw err;
543
- }
340
+ // Remove session method
341
+ const removeSession = async sessionId => {
342
+ await logout(sessionId);
544
343
  };
545
344
 
546
- // Sign up method
547
- const signUp = async (username, email, password) => {
548
- if (!storage) throw new Error('Storage not initialized');
549
- setIsLoading(true);
550
- setError(null);
345
+ // Refresh sessions method
346
+ const refreshSessions = async () => {
347
+ if (!activeSessionId) return;
551
348
  try {
552
- const response = await oxyServices.signUp(username, email, password);
553
- setUser(response.user);
554
-
555
- // Store tokens
556
- await storeTokens(response);
557
-
558
- // Notify about auth state change
559
- if (onAuthStateChange) {
560
- onAuthStateChange(response.user);
561
- }
562
- return response.user;
563
- } catch (err) {
564
- setError(err.message || 'Sign up failed');
565
- throw err;
566
- } finally {
567
- setIsLoading(false);
349
+ const serverSessions = await oxyServices.getSessionsBySessionId(activeSessionId);
350
+
351
+ // Update local sessions with server data
352
+ const updatedSessions = serverSessions.map(serverSession => ({
353
+ sessionId: serverSession.sessionId,
354
+ deviceId: serverSession.deviceId,
355
+ expiresAt: new Date().toISOString(),
356
+ // You might want to get this from server
357
+ lastActive: new Date().toISOString()
358
+ }));
359
+ setSessions(updatedSessions);
360
+ await saveSessionsToStorage(updatedSessions);
361
+ } catch (error) {
362
+ console.error('Refresh sessions error:', error);
568
363
  }
569
364
  };
570
365
 
571
- // Methods to control the bottom sheet
572
- const showBottomSheet = useCallback(screenOrConfig => {
573
- if (bottomSheetRef?.current) {
574
- // Expand the bottom sheet
575
- bottomSheetRef.current.expand();
576
- if (typeof screenOrConfig === 'string') {
577
- // If a screen is specified, navigate to it
578
- if (screenOrConfig && bottomSheetRef.current._navigateToScreen) {
579
- setTimeout(() => {
580
- bottomSheetRef.current._navigateToScreen(screenOrConfig);
581
- }, 100);
582
- }
583
- } else if (screenOrConfig && typeof screenOrConfig === 'object' && screenOrConfig.screen) {
584
- // If an object is passed, navigate and pass props
585
- if (bottomSheetRef.current._navigateToScreen) {
586
- setTimeout(() => {
587
- bottomSheetRef.current._navigateToScreen(screenOrConfig.screen, screenOrConfig.props || {});
588
- }, 100);
589
- }
590
- }
591
- }
592
- }, [bottomSheetRef]);
593
- const hideBottomSheet = useCallback(() => {
594
- if (bottomSheetRef?.current) {
595
- bottomSheetRef.current.close();
596
- }
597
- }, [bottomSheetRef]);
598
-
599
- // Build context value
366
+ // Context value
600
367
  const contextValue = {
601
- // Single user state (current active user)
602
368
  user,
369
+ minimalUser,
370
+ sessions,
371
+ activeSessionId,
603
372
  isAuthenticated: !!user,
604
373
  isLoading,
605
374
  error,
606
- // Multi-user state
607
- users,
608
- // Auth methods
609
375
  login,
610
376
  logout,
611
377
  logoutAll,
612
378
  signUp,
613
- // Multi-user methods
614
- switchUser,
615
- removeUser,
616
- getUserSessions,
617
- logoutSession,
618
- // OxyServices instance
379
+ switchSession,
380
+ removeSession,
381
+ refreshSessions,
619
382
  oxyServices,
620
- // Bottom sheet methods
621
383
  bottomSheetRef,
622
- showBottomSheet,
623
- hideBottomSheet
384
+ showBottomSheet: undefined,
385
+ // Implement as needed
386
+ hideBottomSheet: undefined // Implement as needed
624
387
  };
625
388
  return /*#__PURE__*/_jsx(OxyContext.Provider, {
626
389
  value: contextValue,
@@ -636,4 +399,5 @@ export const useOxy = () => {
636
399
  }
637
400
  return context;
638
401
  };
402
+ export default OxyContext;
639
403
  //# sourceMappingURL=OxyContext.js.map