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