@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.
- package/lib/commonjs/core/index.js +117 -0
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/models/secureSession.js +2 -0
- package/lib/commonjs/models/secureSession.js.map +1 -0
- package/lib/commonjs/ui/context/LegacyOxyContext.js +643 -0
- package/lib/commonjs/ui/context/LegacyOxyContext.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +215 -450
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/SecureOxyContext.js +408 -0
- package/lib/commonjs/ui/context/SecureOxyContext.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +3 -3
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +31 -30
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +4 -4
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +34 -34
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +2 -2
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/core/index.js +117 -0
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/models/secureSession.js +2 -0
- package/lib/module/models/secureSession.js.map +1 -0
- package/lib/module/ui/context/LegacyOxyContext.js +639 -0
- package/lib/module/ui/context/LegacyOxyContext.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +214 -450
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/SecureOxyContext.js +403 -0
- package/lib/module/ui/context/SecureOxyContext.js.map +1 -0
- package/lib/module/ui/screens/AccountCenterScreen.js +3 -3
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +31 -30
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +4 -4
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +34 -34
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +2 -2
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/typescript/core/index.d.ts +51 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/models/secureSession.d.ts +25 -0
- package/lib/typescript/models/secureSession.d.ts.map +1 -0
- package/lib/typescript/ui/context/LegacyOxyContext.d.ts +40 -0
- package/lib/typescript/ui/context/LegacyOxyContext.d.ts.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts +11 -12
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/SecureOxyContext.d.ts +39 -0
- package/lib/typescript/ui/context/SecureOxyContext.d.ts.map +1 -0
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/index.ts +117 -0
- package/src/index.ts +2 -2
- package/src/models/secureSession.ts +27 -0
- package/src/ui/context/LegacyOxyContext.tsx +735 -0
- package/src/ui/context/OxyContext.tsx +412 -674
- package/src/ui/context/SecureOxyContext.tsx +473 -0
- package/src/ui/screens/AccountCenterScreen.tsx +4 -4
- package/src/ui/screens/AccountSwitcherScreen.tsx +36 -34
- package/src/ui/screens/AppInfoScreen.tsx +3 -3
- package/src/ui/screens/SessionManagementScreen.tsx +31 -35
- 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
|
|
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
|
|
65
|
-
|
|
66
|
-
// Array of
|
|
67
|
-
|
|
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 = '
|
|
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 [
|
|
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 =
|
|
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
|
-
//
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
console.log('
|
|
115
|
-
console.log('
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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(
|
|
135
|
+
onAuthStateChange(fullUser);
|
|
146
136
|
}
|
|
147
137
|
} else {
|
|
148
|
-
|
|
149
|
-
|
|
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('
|
|
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
|
|
182
|
-
|
|
183
|
-
//
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
//
|
|
229
|
-
const
|
|
181
|
+
// Save sessions to storage
|
|
182
|
+
const saveSessionsToStorage = (0, _react.useCallback)(async sessionsList => {
|
|
230
183
|
if (!storage) return;
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
//
|
|
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.
|
|
245
|
-
await storage.removeItem(keys.
|
|
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
|
|
200
|
+
console.error('Clear secure storage error:', err);
|
|
250
201
|
}
|
|
251
|
-
};
|
|
202
|
+
}, [storage, keys]);
|
|
252
203
|
|
|
253
|
-
//
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
await
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
}
|
|
274
|
-
|
|
275
|
-
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error('Switch session error:', error);
|
|
227
|
+
setError('Failed to switch session');
|
|
228
|
+
} finally {
|
|
229
|
+
setIsLoading(false);
|
|
276
230
|
}
|
|
277
|
-
|
|
278
|
-
};
|
|
231
|
+
}, [oxyServices, onAuthStateChange, saveActiveSessionId]);
|
|
279
232
|
|
|
280
|
-
//
|
|
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.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
//
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
254
|
+
// Set as active session
|
|
255
|
+
setActiveSessionId(response.sessionId);
|
|
256
|
+
await saveActiveSessionId(response.sessionId);
|
|
313
257
|
|
|
314
|
-
//
|
|
315
|
-
await
|
|
316
|
-
await saveActiveUserId(newUser.id);
|
|
258
|
+
// Get access token for API calls
|
|
259
|
+
await oxyServices.getTokenBySession(response.sessionId);
|
|
317
260
|
|
|
318
|
-
//
|
|
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(
|
|
266
|
+
onAuthStateChange(fullUser);
|
|
321
267
|
}
|
|
322
|
-
return
|
|
323
|
-
} catch (
|
|
324
|
-
setError(
|
|
325
|
-
throw
|
|
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
|
|
332
|
-
const logout = async
|
|
333
|
-
if (!
|
|
334
|
-
setIsLoading(true);
|
|
335
|
-
setError(null);
|
|
277
|
+
// Logout method
|
|
278
|
+
const logout = async targetSessionId => {
|
|
279
|
+
if (!activeSessionId) return;
|
|
336
280
|
try {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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 (
|
|
379
|
-
|
|
380
|
-
|
|
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
|
|
311
|
+
// Logout all sessions
|
|
387
312
|
const logoutAll = async () => {
|
|
388
|
-
if (!
|
|
389
|
-
setIsLoading(true);
|
|
390
|
-
setError(null);
|
|
313
|
+
if (!activeSessionId) return;
|
|
391
314
|
try {
|
|
392
|
-
|
|
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
|
|
403
|
-
|
|
317
|
+
// Clear all local data
|
|
318
|
+
setSessions([]);
|
|
319
|
+
setActiveSessionId(null);
|
|
404
320
|
setUser(null);
|
|
405
|
-
|
|
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 (
|
|
413
|
-
|
|
414
|
-
|
|
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
|
-
//
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
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
|
-
//
|
|
483
|
-
const
|
|
484
|
-
|
|
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
|
-
//
|
|
514
|
-
const
|
|
515
|
-
|
|
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
|
-
//
|
|
549
|
-
const
|
|
550
|
-
if (!
|
|
551
|
-
setIsLoading(true);
|
|
552
|
-
setError(null);
|
|
348
|
+
// Refresh sessions method
|
|
349
|
+
const refreshSessions = async () => {
|
|
350
|
+
if (!activeSessionId) return;
|
|
553
351
|
try {
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
616
|
-
|
|
617
|
-
|
|
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
|
-
|
|
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
|