@oxyhq/services 5.16.33 → 5.16.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -8
- package/lib/commonjs/core/OxyServices.base.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.utility.js.map +1 -1
- package/lib/commonjs/core/services/AuthService.js +156 -0
- package/lib/commonjs/core/services/AuthService.js.map +1 -0
- package/lib/commonjs/core/services/SessionService.js +1 -2
- package/lib/commonjs/core/services/SessionService.js.map +1 -1
- package/lib/commonjs/core/services/SessionTransportService.js +64 -0
- package/lib/commonjs/core/services/SessionTransportService.js.map +1 -0
- package/lib/commonjs/core/services/TokenService.js +9 -17
- package/lib/commonjs/core/services/TokenService.js.map +1 -1
- package/lib/commonjs/core/services/UserService.js +123 -0
- package/lib/commonjs/core/services/UserService.js.map +1 -0
- package/lib/commonjs/core/services/index.js +34 -0
- package/lib/commonjs/core/services/index.js.map +1 -0
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +5 -2
- package/lib/commonjs/crypto/keyManager.js.map +1 -1
- package/lib/commonjs/crypto/signatureService.js +36 -121
- package/lib/commonjs/crypto/signatureService.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +11 -11
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +4 -40
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +23 -61
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +4 -12
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +0 -8
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/index.js +2 -0
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +9 -13
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +11 -26
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/utils/sessionUtils.js +1 -8
- package/lib/commonjs/utils/sessionUtils.js.map +1 -1
- package/lib/module/core/OxyServices.base.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.utility.js.map +1 -1
- package/lib/module/core/services/AuthService.js +151 -0
- package/lib/module/core/services/AuthService.js.map +1 -0
- package/lib/module/core/services/SessionService.js +1 -2
- package/lib/module/core/services/SessionService.js.map +1 -1
- package/lib/module/core/services/SessionTransportService.js +59 -0
- package/lib/module/core/services/SessionTransportService.js.map +1 -0
- package/lib/module/core/services/TokenService.js +9 -17
- package/lib/module/core/services/TokenService.js.map +1 -1
- package/lib/module/core/services/UserService.js +118 -0
- package/lib/module/core/services/UserService.js.map +1 -0
- package/lib/module/core/services/index.js +16 -0
- package/lib/module/core/services/index.js.map +1 -0
- package/lib/module/crypto/index.js +9 -0
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/crypto/keyManager.js +5 -2
- package/lib/module/crypto/keyManager.js.map +1 -1
- package/lib/module/crypto/signatureService.js +36 -122
- package/lib/module/crypto/signatureService.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +11 -11
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +4 -40
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +23 -61
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +5 -13
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +0 -8
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/index.js +1 -0
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +7 -9
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +11 -26
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/utils/sessionUtils.js +1 -8
- package/lib/module/utils/sessionUtils.js.map +1 -1
- package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts +2 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +13 -13
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/core/services/AuthService.d.ts +50 -0
- package/lib/typescript/core/services/AuthService.d.ts.map +1 -0
- package/lib/typescript/core/services/SessionService.d.ts +3 -5
- package/lib/typescript/core/services/SessionService.d.ts.map +1 -1
- package/lib/typescript/core/services/SessionTransportService.d.ts +31 -0
- package/lib/typescript/core/services/SessionTransportService.d.ts.map +1 -0
- package/lib/typescript/core/services/TokenService.d.ts +3 -8
- package/lib/typescript/core/services/TokenService.d.ts.map +1 -1
- package/lib/typescript/core/services/UserService.d.ts +39 -0
- package/lib/typescript/core/services/UserService.d.ts.map +1 -0
- package/lib/typescript/core/services/index.d.ts +13 -0
- package/lib/typescript/core/services/index.d.ts.map +1 -0
- package/lib/typescript/crypto/index.d.ts +9 -0
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
- package/lib/typescript/crypto/signatureService.d.ts +10 -13
- package/lib/typescript/crypto/signatureService.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +15 -69
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +2 -4
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +2 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +2 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts +2 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useLanguageManagement.d.ts +2 -1
- package/lib/typescript/ui/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts +2 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +1 -1
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/ui/utils/sessionHelpers.d.ts +2 -6
- package/lib/typescript/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/utils/sessionUtils.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/core/OxyServices.base.ts +2 -1
- package/src/core/mixins/OxyServices.auth.ts +1 -1
- package/src/core/mixins/OxyServices.user.ts +2 -1
- package/src/core/mixins/OxyServices.utility.ts +2 -1
- package/src/core/services/AuthService.ts +153 -0
- package/src/core/services/SessionService.ts +3 -5
- package/src/core/services/SessionTransportService.ts +69 -0
- package/src/core/services/TokenService.ts +10 -18
- package/src/core/services/UserService.ts +125 -0
- package/src/core/services/index.ts +14 -0
- package/src/crypto/index.ts +9 -0
- package/src/crypto/keyManager.ts +3 -2
- package/src/crypto/signatureService.ts +44 -142
- package/src/index.ts +1 -2
- package/src/models/interfaces.ts +21 -74
- package/src/models/session.ts +3 -5
- package/src/ui/context/OxyContext.tsx +22 -57
- package/src/ui/context/hooks/useAuthOperations.ts +33 -65
- package/src/ui/context/hooks/useLanguageManagement.ts +2 -1
- package/src/ui/hooks/auth/index.ts +0 -2
- package/src/ui/hooks/mutations/useAccountMutations.ts +1 -1
- package/src/ui/hooks/mutations/useServicesMutations.ts +1 -1
- package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
- package/src/ui/hooks/queries/useServicesQueries.ts +3 -8
- package/src/ui/hooks/useLanguageManagement.ts +2 -1
- package/src/ui/hooks/useSessionManagement.ts +3 -9
- package/src/ui/index.ts +2 -1
- package/src/ui/screens/AccountSettingsScreen.tsx +6 -6
- package/src/ui/screens/AccountSwitcherScreen.tsx +1 -1
- package/src/ui/screens/OxyAuthScreen.tsx +5 -9
- package/src/ui/screens/ProfileScreen.tsx +1 -1
- package/src/ui/stores/authStore.ts +1 -1
- package/src/ui/types/navigation.ts +1 -1
- package/src/ui/utils/avatarUtils.ts +1 -1
- package/src/ui/utils/sessionHelpers.ts +15 -32
- package/src/utils/sessionUtils.ts +1 -8
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
|
-
import type { ApiError
|
|
2
|
+
import type { ApiError } from '../../../models/interfaces';
|
|
3
|
+
import type { User } from '@oxyhq/shared';
|
|
3
4
|
import type { AuthState } from '../../stores/authStore';
|
|
4
5
|
import type { ClientSession, SessionLoginResponse } from '../../../models/session';
|
|
5
6
|
import { DeviceManager } from '../../../utils/deviceManager';
|
|
@@ -102,51 +103,26 @@ export const useAuthOperations = ({
|
|
|
102
103
|
const challengeResponse = await oxyServices.requestChallenge(publicKey);
|
|
103
104
|
challenge = challengeResponse.challenge;
|
|
104
105
|
} catch (error) {
|
|
105
|
-
//
|
|
106
|
-
const errorCode = (error as any)?.code;
|
|
107
|
-
const errorStatus = (error as any)?.status;
|
|
106
|
+
// Network error - generate challenge locally for offline sign-in
|
|
108
107
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
const isNetworkError =
|
|
109
|
+
errorMessage.includes('Network') ||
|
|
110
|
+
errorMessage.includes('network') ||
|
|
111
|
+
errorMessage.includes('Failed to fetch') ||
|
|
112
|
+
errorMessage.includes('fetch failed') ||
|
|
113
|
+
(error as any)?.code === 'NETWORK_ERROR' ||
|
|
114
|
+
(error as any)?.status === 0;
|
|
115
|
+
|
|
116
|
+
if (isNetworkError) {
|
|
111
117
|
if (__DEV__ && logger) {
|
|
112
|
-
logger('
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
// Auto-register the user
|
|
116
|
-
const { signature, timestamp } = await SignatureService.createRegistrationSignature();
|
|
117
|
-
await oxyServices.register(publicKey, signature, timestamp);
|
|
118
|
-
|
|
119
|
-
// Retry requesting challenge after registration
|
|
120
|
-
const challengeResponse = await oxyServices.requestChallenge(publicKey);
|
|
121
|
-
challenge = challengeResponse.challenge;
|
|
122
|
-
} catch (registerError) {
|
|
123
|
-
// If registration fails, re-throw the original error
|
|
124
|
-
if (__DEV__ && logger) {
|
|
125
|
-
logger('Auto-registration failed:', registerError);
|
|
126
|
-
}
|
|
127
|
-
throw error; // Re-throw original "not registered" error
|
|
118
|
+
logger('Network unavailable, performing offline sign-in');
|
|
128
119
|
}
|
|
120
|
+
// Generate challenge locally
|
|
121
|
+
challenge = await SignatureService.generateChallenge();
|
|
122
|
+
isOffline = true;
|
|
129
123
|
} else {
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
errorMessage.includes('Network') ||
|
|
133
|
-
errorMessage.includes('network') ||
|
|
134
|
-
errorMessage.includes('Failed to fetch') ||
|
|
135
|
-
errorMessage.includes('fetch failed') ||
|
|
136
|
-
(error as any)?.code === 'NETWORK_ERROR' ||
|
|
137
|
-
errorStatus === 0;
|
|
138
|
-
|
|
139
|
-
if (isNetworkError) {
|
|
140
|
-
if (__DEV__ && logger) {
|
|
141
|
-
logger('Network unavailable, performing offline sign-in');
|
|
142
|
-
}
|
|
143
|
-
// Generate challenge locally
|
|
144
|
-
challenge = await SignatureService.generateChallenge();
|
|
145
|
-
isOffline = true;
|
|
146
|
-
} else {
|
|
147
|
-
// Re-throw non-network errors
|
|
148
|
-
throw error;
|
|
149
|
-
}
|
|
124
|
+
// Re-throw non-network errors
|
|
125
|
+
throw error;
|
|
150
126
|
}
|
|
151
127
|
}
|
|
152
128
|
|
|
@@ -171,9 +147,9 @@ export const useAuthOperations = ({
|
|
|
171
147
|
const localDeviceId = `device_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
172
148
|
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(); // 7 days
|
|
173
149
|
|
|
174
|
-
// Create minimal user object with publicKey as id
|
|
150
|
+
// Create minimal user object with publicKey as id
|
|
175
151
|
fullUser = {
|
|
176
|
-
id: publicKey, // publicKey
|
|
152
|
+
id: publicKey, // Use publicKey as id (per migration document)
|
|
177
153
|
publicKey,
|
|
178
154
|
username: '',
|
|
179
155
|
privacySettings: {},
|
|
@@ -195,7 +171,7 @@ export const useAuthOperations = ({
|
|
|
195
171
|
deviceId: localDeviceId,
|
|
196
172
|
expiresAt,
|
|
197
173
|
lastActive: new Date().toISOString(),
|
|
198
|
-
publicKey,
|
|
174
|
+
userId: publicKey,
|
|
199
175
|
isCurrent: true,
|
|
200
176
|
};
|
|
201
177
|
|
|
@@ -229,10 +205,17 @@ export const useAuthOperations = ({
|
|
|
229
205
|
// Get full user data
|
|
230
206
|
fullUser = await oxyServices.getUserBySession(sessionResponse.sessionId);
|
|
231
207
|
|
|
232
|
-
// user.id
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
208
|
+
// IMPORTANT: user.id should be MongoDB ObjectId, not publicKey
|
|
209
|
+
// The API should return the correct id (ObjectId) from the database
|
|
210
|
+
// If it doesn't, we need to fix the API, not work around it here
|
|
211
|
+
// Validate that id is ObjectId format (24 hex characters)
|
|
212
|
+
if (fullUser.id && !/^[0-9a-fA-F]{24}$/.test(fullUser.id)) {
|
|
213
|
+
console.warn('[useAuthOperations] User.id is not MongoDB ObjectId format:', {
|
|
214
|
+
id: fullUser.id.substring(0, 20),
|
|
215
|
+
publicKey: fullUser.publicKey.substring(0, 20),
|
|
216
|
+
message: 'API should return MongoDB ObjectId as user.id, not publicKey'
|
|
217
|
+
});
|
|
218
|
+
// Don't override - let the API fix this issue
|
|
236
219
|
}
|
|
237
220
|
|
|
238
221
|
// Fetch device sessions
|
|
@@ -240,8 +223,7 @@ export const useAuthOperations = ({
|
|
|
240
223
|
try {
|
|
241
224
|
allDeviceSessions = await fetchSessionsWithFallback(oxyServices, sessionResponse.sessionId, {
|
|
242
225
|
fallbackDeviceId: sessionResponse.deviceId,
|
|
243
|
-
fallbackUserId: fullUser.id,
|
|
244
|
-
fallbackPublicKey: fullUser.publicKey || fullUser.id, // publicKey is canonical identity
|
|
226
|
+
fallbackUserId: fullUser.id,
|
|
245
227
|
logger,
|
|
246
228
|
});
|
|
247
229
|
} catch (error) {
|
|
@@ -311,13 +293,6 @@ export const useAuthOperations = ({
|
|
|
311
293
|
setAuthState({ isLoading: true, error: null });
|
|
312
294
|
|
|
313
295
|
try {
|
|
314
|
-
// SESSION CLEANUP: Clear all sessions before creating new identity
|
|
315
|
-
// New identity means old sessions are no longer valid
|
|
316
|
-
await clearSessionState();
|
|
317
|
-
if (__DEV__ && logger) {
|
|
318
|
-
logger('Cleared all sessions before creating new identity');
|
|
319
|
-
}
|
|
320
|
-
|
|
321
296
|
// Generate new key pair directly (works offline)
|
|
322
297
|
const { publicKey, privateKey } = await KeyManager.generateKeyPair();
|
|
323
298
|
await KeyManager.importKeyPair(privateKey);
|
|
@@ -489,13 +464,6 @@ export const useAuthOperations = ({
|
|
|
489
464
|
setAuthState({ isLoading: true, error: null });
|
|
490
465
|
|
|
491
466
|
try {
|
|
492
|
-
// SESSION CLEANUP: Clear all sessions before importing new identity
|
|
493
|
-
// Importing a different identity means old sessions are no longer valid
|
|
494
|
-
await clearSessionState();
|
|
495
|
-
if (__DEV__ && logger) {
|
|
496
|
-
logger('Cleared all sessions before importing identity');
|
|
497
|
-
}
|
|
498
|
-
|
|
499
467
|
// Decrypt private key from backup data
|
|
500
468
|
const Crypto = await import('expo-crypto');
|
|
501
469
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import type { ApiError
|
|
2
|
+
import type { ApiError } from '../../../models/interfaces';
|
|
3
|
+
import type { User } from '@oxyhq/shared';
|
|
3
4
|
import {
|
|
4
5
|
getLanguageMetadata,
|
|
5
6
|
getLanguageName,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '
|
|
2
|
+
import type { User } from '@oxyhq/shared';
|
|
3
3
|
import { queryKeys, invalidateAccountQueries, invalidateUserQueries } from '../queries/queryKeys';
|
|
4
4
|
import { useOxy } from '../../context/OxyContext';
|
|
5
5
|
import { toast } from '../../../lib/sonner';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '
|
|
2
|
+
import type { User } from '@oxyhq/shared';
|
|
3
3
|
import { queryKeys, invalidateSessionQueries } from '../queries/queryKeys';
|
|
4
4
|
import { useOxy } from '../../context/OxyContext';
|
|
5
5
|
import { toast } from '../../../lib/sonner';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery, useQueries } from '@tanstack/react-query';
|
|
2
|
-
import type { User } from '
|
|
2
|
+
import type { User } from '@oxyhq/shared';
|
|
3
3
|
import type { OxyServices } from '../../../core';
|
|
4
4
|
import { queryKeys } from './queryKeys';
|
|
5
5
|
import { useOxy } from '../../context/OxyContext';
|
|
@@ -8,7 +8,7 @@ import { fetchSessionsWithFallback, mapSessionsToClient } from '../../utils/sess
|
|
|
8
8
|
* Get all active sessions for the current user
|
|
9
9
|
*/
|
|
10
10
|
export const useSessions = (userId?: string, options?: { enabled?: boolean }) => {
|
|
11
|
-
const { oxyServices, activeSessionId
|
|
11
|
+
const { oxyServices, activeSessionId } = useOxy();
|
|
12
12
|
|
|
13
13
|
return useQuery({
|
|
14
14
|
queryKey: queryKeys.sessions.list(userId),
|
|
@@ -17,14 +17,12 @@ export const useSessions = (userId?: string, options?: { enabled?: boolean }) =>
|
|
|
17
17
|
throw new Error('No active session');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const publicKey = user?.publicKey || user?.id || ''; // user.id is now publicKey
|
|
21
20
|
const sessions = await fetchSessionsWithFallback(oxyServices, activeSessionId, {
|
|
22
21
|
fallbackDeviceId: undefined,
|
|
23
22
|
fallbackUserId: userId,
|
|
24
|
-
fallbackPublicKey: publicKey,
|
|
25
23
|
});
|
|
26
24
|
|
|
27
|
-
return sessions;
|
|
25
|
+
return mapSessionsToClient(sessions, activeSessionId);
|
|
28
26
|
},
|
|
29
27
|
enabled: (options?.enabled !== false) && !!activeSessionId,
|
|
30
28
|
staleTime: 2 * 60 * 1000, // 2 minutes (sessions change frequently)
|
|
@@ -51,15 +49,12 @@ export const useSession = (sessionId: string | null, options?: { enabled?: boole
|
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
const now = new Date();
|
|
54
|
-
// user.id is now publicKey (canonical identity)
|
|
55
|
-
const publicKey = validation.user.publicKey || validation.user.id || '';
|
|
56
52
|
return {
|
|
57
53
|
sessionId,
|
|
58
54
|
deviceId: '', // Device ID not available from validation response
|
|
59
55
|
expiresAt: validation.expiresAt || new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
60
56
|
lastActive: validation.lastActivity || now.toISOString(),
|
|
61
|
-
|
|
62
|
-
userId: validation.user.id?.toString(), // Optional MongoDB ObjectId
|
|
57
|
+
userId: validation.user.id?.toString() ?? '',
|
|
63
58
|
isCurrent: false,
|
|
64
59
|
} as ClientSession;
|
|
65
60
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
-
import type { ApiError
|
|
2
|
+
import type { ApiError } from '../../models/interfaces';
|
|
3
|
+
import type { User } from '@oxyhq/shared';
|
|
3
4
|
import {
|
|
4
5
|
getLanguageMetadata,
|
|
5
6
|
getLanguageName,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import type { ApiError
|
|
2
|
+
import type { ApiError } from '../../models/interfaces';
|
|
3
|
+
import type { User } from '@oxyhq/shared';
|
|
3
4
|
import type { ClientSession } from '../../models/session';
|
|
4
5
|
import { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual } from '../../utils/sessionUtils';
|
|
5
6
|
import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch } from '../utils/sessionHelpers';
|
|
@@ -255,10 +256,8 @@ export const useSessionManagement = ({
|
|
|
255
256
|
await activateSession(sessionId, user);
|
|
256
257
|
|
|
257
258
|
try {
|
|
258
|
-
const publicKey = user.publicKey || user.id || ''; // user.id is now publicKey
|
|
259
259
|
const deviceSessions = await fetchSessionsWithFallback(oxyServices, sessionId, {
|
|
260
|
-
fallbackUserId: user.id,
|
|
261
|
-
fallbackPublicKey: publicKey,
|
|
260
|
+
fallbackUserId: user.id,
|
|
262
261
|
logger,
|
|
263
262
|
});
|
|
264
263
|
updateSessions(deviceSessions, { merge: true });
|
|
@@ -332,13 +331,8 @@ export const useSessionManagement = ({
|
|
|
332
331
|
|
|
333
332
|
const refreshPromise = (async () => {
|
|
334
333
|
try {
|
|
335
|
-
// Get publicKey from active session or current user
|
|
336
|
-
const activeSession = sessions.find(s => s.sessionId === activeSessionId);
|
|
337
|
-
const publicKey = activeSession?.publicKey || activeUserId || ''; // Fallback to userId if publicKey not available
|
|
338
|
-
|
|
339
334
|
const deviceSessions = await fetchSessionsWithFallback(oxyServices, activeSessionId, {
|
|
340
335
|
fallbackUserId: activeUserId,
|
|
341
|
-
fallbackPublicKey: publicKey,
|
|
342
336
|
logger,
|
|
343
337
|
});
|
|
344
338
|
updateSessions(deviceSessions, { merge: true });
|
package/src/ui/index.ts
CHANGED
|
@@ -81,4 +81,5 @@ export {
|
|
|
81
81
|
|
|
82
82
|
// Re-export core services for convenience in UI context
|
|
83
83
|
export { OxyServices } from '../core';
|
|
84
|
-
|
|
84
|
+
// Note: User and LoginResponse should be imported from @oxyhq/shared
|
|
85
|
+
export type { ApiError } from '../models/interfaces';
|
|
@@ -233,7 +233,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
233
233
|
|
|
234
234
|
// Handle locations - convert single location to array format
|
|
235
235
|
if (finalUser.locations && Array.isArray(finalUser.locations)) {
|
|
236
|
-
setLocations(finalUser.locations.map((loc, index) => ({
|
|
236
|
+
setLocations(finalUser.locations.map((loc: any, index: number) => ({
|
|
237
237
|
id: loc.id || `existing-${index}`,
|
|
238
238
|
name: loc.name,
|
|
239
239
|
label: loc.label,
|
|
@@ -252,17 +252,17 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
252
252
|
|
|
253
253
|
// Handle links - simple and direct like other fields
|
|
254
254
|
if (finalUser.linksMetadata && Array.isArray(finalUser.linksMetadata)) {
|
|
255
|
-
const urls = finalUser.linksMetadata.map(l => l.url);
|
|
255
|
+
const urls = finalUser.linksMetadata.map((l: any) => l.url);
|
|
256
256
|
setLinks(urls);
|
|
257
|
-
const metadataWithIds = finalUser.linksMetadata.map((link, index) => ({
|
|
257
|
+
const metadataWithIds = finalUser.linksMetadata.map((link: any, index: number) => ({
|
|
258
258
|
...link,
|
|
259
259
|
id: link.id || `existing-${index}`
|
|
260
260
|
}));
|
|
261
261
|
setLinksMetadata(metadataWithIds);
|
|
262
262
|
} else if (Array.isArray(finalUser.links)) {
|
|
263
|
-
const simpleLinks = finalUser.links.map(l => typeof l === 'string' ? l : l.link).filter(Boolean);
|
|
263
|
+
const simpleLinks = finalUser.links.map((l: any) => typeof l === 'string' ? l : l.link).filter(Boolean);
|
|
264
264
|
setLinks(simpleLinks);
|
|
265
|
-
const linksWithMetadata = simpleLinks.map((url, index) => ({
|
|
265
|
+
const linksWithMetadata = simpleLinks.map((url: string, index: number) => ({
|
|
266
266
|
url,
|
|
267
267
|
title: url.replace(/^https?:\/\//, '').replace(/\/$/, ''),
|
|
268
268
|
description: `Link to ${url}`,
|
|
@@ -553,7 +553,7 @@ const AccountSettingsScreen: React.FC<BaseScreenProps & { initialField?: string;
|
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
if (currentUser.linksMetadata && Array.isArray(currentUser.linksMetadata)) {
|
|
556
|
-
setLinksMetadata(currentUser.linksMetadata.map((link, index) => ({
|
|
556
|
+
setLinksMetadata(currentUser.linksMetadata.map((link: any, index: number) => ({
|
|
557
557
|
...link,
|
|
558
558
|
id: link.id || `existing-${index}`
|
|
559
559
|
})));
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import type { BaseScreenProps } from '../types/navigation';
|
|
16
16
|
import type { ClientSession } from '../../models/session';
|
|
17
17
|
import { fontFamilies } from '../styles/fonts';
|
|
18
|
-
import type { User } from '
|
|
18
|
+
import type { User } from '@oxyhq/shared';
|
|
19
19
|
import { toast } from '../../lib/sonner';
|
|
20
20
|
import { confirmAction } from '../utils/confirmAction';
|
|
21
21
|
import OxyIcon from '../components/icon/OxyIcon';
|
|
@@ -220,7 +220,7 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
220
220
|
|
|
221
221
|
try {
|
|
222
222
|
// Generate a unique session token for this auth request
|
|
223
|
-
const sessionToken = generateSessionToken();
|
|
223
|
+
const sessionToken = await generateSessionToken();
|
|
224
224
|
const expiresAt = Date.now() + AUTH_SESSION_EXPIRY_MS;
|
|
225
225
|
|
|
226
226
|
// Register the auth session with the server
|
|
@@ -242,14 +242,10 @@ const OxyAuthScreen: React.FC<BaseScreenProps> = ({
|
|
|
242
242
|
}
|
|
243
243
|
}, [oxyServices, connectSocket]);
|
|
244
244
|
|
|
245
|
-
// Generate a random session token
|
|
246
|
-
const generateSessionToken = (): string => {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
for (let i = 0; i < 32; i++) {
|
|
250
|
-
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
251
|
-
}
|
|
252
|
-
return result;
|
|
245
|
+
// Generate a random session token using secure random bytes
|
|
246
|
+
const generateSessionToken = async (): Promise<string> => {
|
|
247
|
+
const { generateSessionToken: sharedGenerate } = await import('@oxyhq/shared');
|
|
248
|
+
return sharedGenerate(32); // 32 bytes = 64 hex characters
|
|
253
249
|
};
|
|
254
250
|
|
|
255
251
|
// Clean up on unmount
|
|
@@ -10,7 +10,7 @@ import { Ionicons } from '@expo/vector-icons';
|
|
|
10
10
|
import { useI18n } from '../hooks/useI18n';
|
|
11
11
|
import { useOxy } from '../context/OxyContext';
|
|
12
12
|
import { logger } from '../../utils/loggerUtils';
|
|
13
|
-
import type { User } from '
|
|
13
|
+
import type { User } from '@oxyhq/shared';
|
|
14
14
|
import { extractErrorMessage } from '../utils/errorHandlers';
|
|
15
15
|
|
|
16
16
|
interface ProfileScreenProps extends BaseScreenProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ReactNode, RefObject } from 'react';
|
|
2
2
|
import type { QueryClient } from '@tanstack/react-query';
|
|
3
3
|
import type { RouteName } from '../navigation/routes';
|
|
4
|
-
import type { User } from '
|
|
4
|
+
import type { User } from '@oxyhq/shared';
|
|
5
5
|
import type { ClientSession } from '../../models/session';
|
|
6
6
|
|
|
7
7
|
// Re-export RouteName from routes for convenience
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OxyServices } from '../../core';
|
|
2
|
-
import type { User } from '
|
|
2
|
+
import type { User } from '@oxyhq/shared';
|
|
3
3
|
import { useAccountStore } from '../stores/accountStore';
|
|
4
4
|
import { useAuthStore } from '../stores/authStore';
|
|
5
5
|
import { QueryClient } from '@tanstack/react-query';
|
|
@@ -7,16 +7,14 @@ interface DeviceSession {
|
|
|
7
7
|
deviceName?: string;
|
|
8
8
|
expiresAt?: string;
|
|
9
9
|
lastActive?: string;
|
|
10
|
-
user?: { id?: string;
|
|
10
|
+
user?: { id?: string; _id?: { toString(): string } };
|
|
11
11
|
userId?: string;
|
|
12
|
-
publicKey?: string;
|
|
13
12
|
isCurrent?: boolean;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
export interface FetchSessionsWithFallbackOptions {
|
|
17
16
|
fallbackDeviceId?: string;
|
|
18
17
|
fallbackUserId?: string;
|
|
19
|
-
fallbackPublicKey?: string; // Canonical user identity
|
|
20
18
|
logger?: (message: string, error?: unknown) => void;
|
|
21
19
|
}
|
|
22
20
|
|
|
@@ -39,41 +37,27 @@ export interface SessionValidationResult {
|
|
|
39
37
|
* @param sessions - Raw session array returned from the API
|
|
40
38
|
* @param fallbackDeviceId - Device identifier to use when missing from payload
|
|
41
39
|
* @param fallbackUserId - User identifier to use when missing from payload
|
|
42
|
-
* @param fallbackPublicKey - Public key to use when missing from payload (canonical identity)
|
|
43
40
|
*/
|
|
44
41
|
export const mapSessionsToClient = (
|
|
45
42
|
sessions: DeviceSession[],
|
|
46
43
|
fallbackDeviceId?: string,
|
|
47
44
|
fallbackUserId?: string,
|
|
48
|
-
fallbackPublicKey?: string,
|
|
49
45
|
): ClientSession[] => {
|
|
50
46
|
const now = new Date();
|
|
51
47
|
|
|
52
|
-
return sessions.map((session) => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
session.
|
|
59
|
-
fallbackPublicKey ||
|
|
60
|
-
'';
|
|
61
|
-
|
|
62
|
-
// userId is MongoDB ObjectId (internal backend reference, optional)
|
|
63
|
-
const userId =
|
|
48
|
+
return sessions.map((session) => ({
|
|
49
|
+
sessionId: session.sessionId,
|
|
50
|
+
deviceId: session.deviceId || fallbackDeviceId || '',
|
|
51
|
+
expiresAt: session.expiresAt || new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
52
|
+
lastActive: session.lastActive || now.toISOString(),
|
|
53
|
+
userId:
|
|
54
|
+
session.user?.id ||
|
|
64
55
|
session.userId ||
|
|
65
|
-
(session.user?._id ? session.user._id.toString() : undefined)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expiresAt: session.expiresAt || new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
71
|
-
lastActive: session.lastActive || now.toISOString(),
|
|
72
|
-
publicKey, // Canonical user identity - REQUIRED
|
|
73
|
-
userId, // MongoDB ObjectId (optional, for backward compatibility)
|
|
74
|
-
isCurrent: Boolean(session.isCurrent),
|
|
75
|
-
};
|
|
76
|
-
});
|
|
56
|
+
(session.user?._id ? session.user._id.toString() : undefined) ||
|
|
57
|
+
fallbackUserId ||
|
|
58
|
+
'',
|
|
59
|
+
isCurrent: Boolean(session.isCurrent),
|
|
60
|
+
}));
|
|
77
61
|
};
|
|
78
62
|
|
|
79
63
|
/**
|
|
@@ -89,20 +73,19 @@ export const fetchSessionsWithFallback = async (
|
|
|
89
73
|
{
|
|
90
74
|
fallbackDeviceId,
|
|
91
75
|
fallbackUserId,
|
|
92
|
-
fallbackPublicKey,
|
|
93
76
|
logger,
|
|
94
77
|
}: FetchSessionsWithFallbackOptions = {},
|
|
95
78
|
): Promise<ClientSession[]> => {
|
|
96
79
|
try {
|
|
97
80
|
const deviceSessions = await oxyServices.getDeviceSessions(sessionId);
|
|
98
|
-
return mapSessionsToClient(deviceSessions, fallbackDeviceId, fallbackUserId
|
|
81
|
+
return mapSessionsToClient(deviceSessions, fallbackDeviceId, fallbackUserId);
|
|
99
82
|
} catch (error) {
|
|
100
83
|
if (__DEV__ && logger) {
|
|
101
84
|
logger('Failed to get device sessions, falling back to user sessions', error);
|
|
102
85
|
}
|
|
103
86
|
|
|
104
87
|
const userSessions = await oxyServices.getSessionsBySessionId(sessionId);
|
|
105
|
-
return mapSessionsToClient(userSessions, fallbackDeviceId, fallbackUserId
|
|
88
|
+
return mapSessionsToClient(userSessions, fallbackDeviceId, fallbackUserId);
|
|
106
89
|
}
|
|
107
90
|
};
|
|
108
91
|
|
|
@@ -12,19 +12,12 @@ import type { ClientSession } from '../models/session';
|
|
|
12
12
|
*/
|
|
13
13
|
export function normalizeSession(session: Partial<ClientSession> & { sessionId: string }): ClientSession {
|
|
14
14
|
const now = new Date().toISOString();
|
|
15
|
-
|
|
16
|
-
// publicKey is required (canonical user identity)
|
|
17
|
-
if (!session.publicKey) {
|
|
18
|
-
throw new Error(`Session ${session.sessionId} is missing required publicKey field`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
15
|
return {
|
|
22
16
|
sessionId: session.sessionId,
|
|
23
17
|
deviceId: session.deviceId || '',
|
|
24
18
|
expiresAt: session.expiresAt || now,
|
|
25
19
|
lastActive: session.lastActive || now,
|
|
26
|
-
|
|
27
|
-
userId: session.userId, // Optional MongoDB ObjectId for backward compatibility
|
|
20
|
+
userId: session.userId || '',
|
|
28
21
|
};
|
|
29
22
|
}
|
|
30
23
|
|