@onairos/react-native 3.0.74 → 3.1.0

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 (49) hide show
  1. package/lib/commonjs/components/EmailVerificationModal.js +7 -5
  2. package/lib/commonjs/components/EmailVerificationModal.js.map +1 -1
  3. package/lib/commonjs/components/UniversalOnboarding.js +10 -1
  4. package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
  5. package/lib/commonjs/index.js +0 -6
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/services/apiKeyService.js +278 -27
  8. package/lib/commonjs/services/apiKeyService.js.map +1 -1
  9. package/lib/commonjs/services/platformAuthService.js +127 -290
  10. package/lib/commonjs/services/platformAuthService.js.map +1 -1
  11. package/lib/commonjs/utils/onairosApi.js +143 -71
  12. package/lib/commonjs/utils/onairosApi.js.map +1 -1
  13. package/lib/commonjs/utils/secureStorage.js +123 -1
  14. package/lib/commonjs/utils/secureStorage.js.map +1 -1
  15. package/lib/module/components/EmailVerificationModal.js +7 -5
  16. package/lib/module/components/EmailVerificationModal.js.map +1 -1
  17. package/lib/module/components/UniversalOnboarding.js +11 -2
  18. package/lib/module/components/UniversalOnboarding.js.map +1 -1
  19. package/lib/module/index.js +3 -1
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/services/apiKeyService.js +264 -22
  22. package/lib/module/services/apiKeyService.js.map +1 -1
  23. package/lib/module/services/platformAuthService.js +125 -287
  24. package/lib/module/services/platformAuthService.js.map +1 -1
  25. package/lib/module/utils/onairosApi.js +139 -70
  26. package/lib/module/utils/onairosApi.js.map +1 -1
  27. package/lib/module/utils/secureStorage.js +116 -0
  28. package/lib/module/utils/secureStorage.js.map +1 -1
  29. package/lib/typescript/components/EmailVerificationModal.d.ts.map +1 -1
  30. package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
  31. package/lib/typescript/index.d.ts +1 -1
  32. package/lib/typescript/index.d.ts.map +1 -1
  33. package/lib/typescript/services/apiKeyService.d.ts +50 -2
  34. package/lib/typescript/services/apiKeyService.d.ts.map +1 -1
  35. package/lib/typescript/services/platformAuthService.d.ts +29 -14
  36. package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
  37. package/lib/typescript/utils/onairosApi.d.ts +24 -10
  38. package/lib/typescript/utils/onairosApi.d.ts.map +1 -1
  39. package/lib/typescript/utils/secureStorage.d.ts +31 -0
  40. package/lib/typescript/utils/secureStorage.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/components/EmailVerificationModal.tsx +9 -5
  43. package/src/components/UniversalOnboarding.tsx +11 -1
  44. package/src/index.ts +1 -1
  45. package/src/services/apiKeyService.ts +282 -18
  46. package/src/services/platformAuthService.ts +216 -412
  47. package/src/types/index.d.ts +6 -5
  48. package/src/utils/onairosApi.ts +151 -74
  49. package/src/utils/secureStorage.ts +122 -0
@@ -1,51 +1,36 @@
1
1
  import { Platform, Linking } from 'react-native';
2
2
  import AsyncStorage from '@react-native-async-storage/async-storage';
3
3
  import type { PlatformAuthConfig } from '../types';
4
- import { makeAuthenticatedRequest, getApiConfig } from './apiKeyService';
4
+ import { makeDeveloperRequest, getApiConfig, storeJWT } from './apiKeyService';
5
5
 
6
- // 🔑 CRITICAL: Initialize API key service for authentication
7
- let isApiKeyInitialized = false;
6
+ // 🔑 CRITICAL: Use two-tier authentication system
7
+ // - Developer API key for email verification requests
8
+ // - JWT tokens for user-authenticated requests after email verification
8
9
 
9
10
  /**
10
- * Initialize the API key service with the admin key for testing
11
- * This ensures all API requests include proper authentication headers
11
+ * Initialize the platform auth service
12
+ * This service now uses the two-tier authentication system
12
13
  */
13
14
  export const initializePlatformAuthService = async (): Promise<void> => {
14
- if (isApiKeyInitialized) {
15
- console.log('🔑 API key service already initialized');
16
- return;
17
- }
18
-
19
15
  try {
20
- // Import the initialization function
21
- const { initializeApiKey, ADMIN_API_KEY } = await import('./apiKeyService');
16
+ // Check if app is already initialized with API key
17
+ const existingConfig = getApiConfig();
22
18
 
23
- // Initialize with admin key for production email service
24
- await initializeApiKey({
25
- apiKey: ADMIN_API_KEY, // 'OnairosIsAUnicorn2025'
26
- environment: 'production', // Use production for email verification
27
- enableLogging: true,
28
- timeout: 30000,
29
- });
30
-
31
- isApiKeyInitialized = true;
32
- console.log('✅ Platform auth service initialized with admin key (production)');
19
+ if (existingConfig && existingConfig.apiKey) {
20
+ console.log('🔑 Platform auth service using existing app configuration');
21
+ console.log(`✅ Environment: ${existingConfig.environment}`);
22
+ return;
23
+ }
24
+
25
+ // If no app initialization, we can't proceed
26
+ console.error('❌ Platform auth service requires app-level API key initialization');
27
+ throw new Error('Platform auth service requires app-level API key initialization. Please call initializeApiKey() first.');
33
28
  } catch (error) {
34
29
  console.error('❌ Failed to initialize platform auth service:', error);
35
30
  throw error;
36
31
  }
37
32
  };
38
33
 
39
- /**
40
- * Ensure API key is initialized before making authenticated requests
41
- */
42
- const ensureApiKeyInitialized = async (): Promise<void> => {
43
- if (!isApiKeyInitialized) {
44
- console.log('🔑 API key not initialized, initializing now...');
45
- await initializePlatformAuthService();
46
- }
47
- };
48
-
49
34
  // Configuration for each platform's authentication
50
35
  let PLATFORM_AUTH_CONFIG: Record<string, PlatformAuthConfig> = {
51
36
  instagram: {
@@ -156,7 +141,7 @@ export const initiateOAuth = async (platform: string, username: string, appName?
156
141
 
157
142
  console.log('📤 Sending Instagram OAuth request:', jsonData);
158
143
 
159
- const response = await makeAuthenticatedRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
144
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
160
145
  method: 'POST',
161
146
  body: JSON.stringify(jsonData),
162
147
  });
@@ -199,7 +184,7 @@ export const initiateOAuth = async (platform: string, username: string, appName?
199
184
  console.log(`📤 Sending ${platform} OAuth request:`, jsonData);
200
185
 
201
186
  // Make the authenticated request to get the OAuth URL
202
- const response = await makeAuthenticatedRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
187
+ const response = await makeDeveloperRequest(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
203
188
  method: 'POST',
204
189
  body: JSON.stringify(jsonData),
205
190
  });
@@ -331,68 +316,68 @@ const validateOAuthUrl = async (url: string): Promise<boolean> => {
331
316
  * @returns A Promise that resolves to the authentication result
332
317
  */
333
318
  export const initiateNativeAuth = async (platform: string, username?: string): Promise<boolean> => {
334
- if (platform === 'youtube') {
319
+ if (platform === 'youtube') {
335
320
  console.log('🔗 Initiating native Google Sign-In for YouTube');
321
+ try {
322
+ // Check if Google Sign-In package is available
323
+ let GoogleSignin, statusCodes;
336
324
  try {
337
- // Check if Google Sign-In package is available
338
- let GoogleSignin, statusCodes;
339
- try {
340
- const googleSignInModule = require('@react-native-google-signin/google-signin');
341
- GoogleSignin = googleSignInModule.GoogleSignin;
342
- statusCodes = googleSignInModule.statusCodes;
343
- } catch (importError) {
344
- console.error('❌ Google Sign-In package not available:', importError);
345
- throw new Error('Google Sign-In SDK not installed. Please install @react-native-google-signin/google-signin');
346
- }
347
-
348
- // Configure Google Sign-In with better error handling
349
- try {
350
- await GoogleSignin.configure({
351
- webClientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
352
- iosClientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
353
- scopes: ['https://www.googleapis.com/auth/youtube.readonly'],
354
- offlineAccess: true,
355
- hostedDomain: '',
356
- forceCodeForRefreshToken: true,
357
- accountName: '',
358
- });
359
- console.log('✅ Google Sign-In configured successfully');
360
- } catch (configError) {
361
- console.error('❌ Google Sign-In configuration failed:', configError);
362
- throw new Error(`Google Sign-In configuration failed: ${configError.message || configError}`);
363
- }
364
-
365
- // Check if Google Play Services are available (Android only)
366
- try {
367
- await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true });
368
- console.log('✅ Google Play Services available');
369
- } catch (playServicesError) {
370
- console.error('❌ Google Play Services error:', playServicesError);
371
- throw new Error(`Google Play Services not available: ${playServicesError.message || playServicesError}`);
372
- }
325
+ const googleSignInModule = require('@react-native-google-signin/google-signin');
326
+ GoogleSignin = googleSignInModule.GoogleSignin;
327
+ statusCodes = googleSignInModule.statusCodes;
328
+ } catch (importError) {
329
+ console.error('❌ Google Sign-In package not available:', importError);
330
+ throw new Error('Google Sign-In SDK not installed. Please install @react-native-google-signin/google-signin');
331
+ }
332
+
333
+ // Configure Google Sign-In with better error handling
334
+ try {
335
+ await GoogleSignin.configure({
336
+ webClientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
337
+ iosClientId: '1030678346906-lovkuds2ouqmoc8eu5qpo98spa6edv4o.apps.googleusercontent.com',
338
+ scopes: ['https://www.googleapis.com/auth/youtube.readonly'],
339
+ offlineAccess: true,
340
+ hostedDomain: '',
341
+ forceCodeForRefreshToken: true,
342
+ accountName: '',
343
+ });
344
+ console.log('✅ Google Sign-In configured successfully');
345
+ } catch (configError) {
346
+ console.error('❌ Google Sign-In configuration failed:', configError);
347
+ throw new Error(`Google Sign-In configuration failed: ${configError.message || configError}`);
348
+ }
349
+
350
+ // Check if Google Play Services are available (Android only)
351
+ try {
352
+ await GoogleSignin.hasPlayServices({ showPlayServicesUpdateDialog: true });
353
+ console.log('✅ Google Play Services available');
354
+ } catch (playServicesError) {
355
+ console.error('❌ Google Play Services error:', playServicesError);
356
+ throw new Error(`Google Play Services not available: ${playServicesError.message || playServicesError}`);
357
+ }
358
+
359
+ // Sign in with Google
360
+ let userInfo;
361
+ try {
362
+ userInfo = await GoogleSignin.signIn();
363
+ console.log('✅ Google Sign-In successful:', userInfo.user?.email);
364
+ } catch (signInError) {
365
+ console.error('❌ Google Sign-In failed:', signInError);
373
366
 
374
- // Sign in with Google
375
- let userInfo;
376
- try {
377
- userInfo = await GoogleSignin.signIn();
378
- console.log('Google Sign-In successful:', userInfo.user?.email);
379
- } catch (signInError) {
380
- console.error('Google Sign-In failed:', signInError);
381
-
382
- // Handle specific error codes
383
- if (signInError.code === statusCodes.SIGN_IN_CANCELLED) {
384
- throw new Error('Google Sign-In was cancelled by user');
385
- } else if (signInError.code === statusCodes.IN_PROGRESS) {
386
- throw new Error('Google Sign-In already in progress');
387
- } else if (signInError.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
388
- throw new Error('Google Play Services not available or outdated');
389
- } else {
390
- throw new Error(`Google Sign-In failed: ${signInError.message || signInError}`);
391
- }
367
+ // Handle specific error codes
368
+ if (signInError.code === statusCodes.SIGN_IN_CANCELLED) {
369
+ throw new Error('Google Sign-In was cancelled by user');
370
+ } else if (signInError.code === statusCodes.IN_PROGRESS) {
371
+ throw new Error('Google Sign-In already in progress');
372
+ } else if (signInError.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
373
+ throw new Error('Google Play Services not available or outdated');
374
+ } else {
375
+ throw new Error(`Google Sign-In failed: ${signInError.message || signInError}`);
392
376
  }
393
-
377
+ }
378
+
394
379
  // Get access token for API calls
395
- const tokens = await GoogleSignin.getTokens();
380
+ const tokens = await GoogleSignin.getTokens();
396
381
  console.log('🔑 Got Google tokens');
397
382
 
398
383
  // Get current user info with refresh token
@@ -532,22 +517,22 @@ export const initiateNativeAuth = async (platform: string, username?: string): P
532
517
  return false;
533
518
  }
534
519
 
535
- } catch (error: any) {
520
+ } catch (error: any) {
536
521
  console.error('❌ Google Sign-In error:', error);
537
522
 
538
- const { statusCodes: StatusCodes } = require('@react-native-google-signin/google-signin');
539
-
540
- if (error.code === StatusCodes.SIGN_IN_CANCELLED) {
523
+ const { statusCodes: StatusCodes } = require('@react-native-google-signin/google-signin');
524
+
525
+ if (error.code === StatusCodes.SIGN_IN_CANCELLED) {
541
526
  console.log('User cancelled Google Sign-In');
542
- } else if (error.code === StatusCodes.IN_PROGRESS) {
527
+ } else if (error.code === StatusCodes.IN_PROGRESS) {
543
528
  console.log('Google Sign-In already in progress');
544
- } else if (error.code === StatusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
529
+ } else if (error.code === StatusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
545
530
  console.log('Google Play Services not available');
546
- }
547
-
548
- return false;
549
531
  }
532
+
533
+ return false;
550
534
  }
535
+ }
551
536
 
552
537
  return false;
553
538
  };
@@ -816,413 +801,232 @@ export const updateGoogleClientIds = (config: {
816
801
  };
817
802
 
818
803
  /**
819
- * 📧 EMAIL VERIFICATION FUNCTIONS
820
- * Using the correct Onairos email verification endpoints
804
+ * Request email verification using developer API key
805
+ * @param email Email address to verify
806
+ * @param testMode Whether to use test mode
807
+ * @returns Promise with verification result
821
808
  */
822
- export const requestEmailVerification = async (email: string, testMode = false): Promise<{
823
- success: boolean;
824
- message?: string;
825
- error?: string;
826
- requestId?: string;
827
- }> => {
809
+ export const requestEmailVerification = async (
810
+ email: string,
811
+ testMode: boolean = false
812
+ ): Promise<{ success: boolean; message?: string; error?: string }> => {
828
813
  try {
829
814
  console.log('📧 Requesting email verification for:', email);
830
- console.log('🧪 Test mode:', testMode);
831
815
 
832
- if (!email || !email.includes('@')) {
833
- return {
834
- success: false,
835
- error: 'Valid email address is required',
836
- };
837
- }
838
-
839
- // In test mode, always return success with mock request ID
840
- if (testMode) {
841
- console.log('🧪 Test mode: Always returning success with mock request ID');
842
- const mockRequestId = 'test-request-' + Date.now();
843
-
844
- // Store request info for tracking
845
- await AsyncStorage.setItem('email_verification_request_id', mockRequestId);
846
- await AsyncStorage.setItem('email_verification_request_email', email);
847
-
816
+ const response = await makeDeveloperRequest('/email/verification', {
817
+ method: 'POST',
818
+ body: JSON.stringify({
819
+ email,
820
+ action: 'request',
821
+ testMode
822
+ })
823
+ });
824
+
825
+ const data = await response.json();
826
+
827
+ if (response.ok && data.success) {
828
+ console.log('✅ Email verification requested successfully');
848
829
  return {
849
830
  success: true,
850
- message: 'Email verification sent successfully (test mode)',
851
- requestId: mockRequestId,
831
+ message: data.message || 'Verification code sent to your email'
852
832
  };
853
- }
854
-
855
- // Production mode: Make real API call with API key authentication
856
- try {
857
- // 🔑 Ensure API key is initialized before making authenticated requests
858
- await ensureApiKeyInitialized();
859
-
860
- const response = await makeAuthenticatedRequest('/email/verification', {
861
- method: 'POST',
862
- body: JSON.stringify({
863
- email,
864
- action: 'request',
865
- }),
866
- });
867
-
868
- const result = await response.json();
869
- console.log('📡 Email verification API response:', result);
870
-
871
- if (response.ok && result.success) {
872
- console.log('✅ Email verification request sent');
873
-
874
- // Store request info for tracking
875
- const requestId = result.requestId || result.id || ('req-' + Date.now());
876
- await AsyncStorage.setItem('email_verification_request_id', requestId);
877
- await AsyncStorage.setItem('email_verification_request_email', email);
878
-
879
- return {
880
- success: true,
881
- message: result.message || 'Email verification sent successfully',
882
- requestId: requestId,
883
- };
884
- } else {
885
- console.error('❌ Email verification request failed:', result.error);
886
- return {
887
- success: false,
888
- error: result.error || 'Failed to send verification email',
889
- };
890
- }
891
- } catch (apiError) {
892
- console.error('❌ Email verification API call failed:', apiError);
833
+ } else {
834
+ console.error('❌ Email verification request failed:', data.error);
893
835
  return {
894
836
  success: false,
895
- error: 'Network error while sending verification email',
837
+ error: data.error || 'Failed to send verification code'
896
838
  };
897
839
  }
898
840
  } catch (error) {
899
- console.error('❌ Email verification request error:', error);
841
+ console.error('❌ Error requesting email verification:', error);
900
842
  return {
901
843
  success: false,
902
- error: error instanceof Error ? error.message : 'Unknown error',
844
+ error: error instanceof Error ? error.message : 'Network error'
903
845
  };
904
846
  }
905
847
  };
906
848
 
907
- export const verifyEmailCode = async (email: string, code: string, testMode = false): Promise<{
908
- success: boolean;
909
- message?: string;
910
- error?: string;
911
- existingUser?: boolean;
912
- jwtToken?: string;
913
- }> => {
849
+ /**
850
+ * Verify email code and store JWT token
851
+ * @param email Email address
852
+ * @param code Verification code
853
+ * @param testMode Whether to use test mode
854
+ * @returns Promise with verification result and JWT token
855
+ */
856
+ export const verifyEmailCode = async (
857
+ email: string,
858
+ code: string,
859
+ testMode: boolean = false
860
+ ): Promise<{ success: boolean; message?: string; error?: string; existingUser?: boolean; token?: string }> => {
914
861
  try {
915
862
  console.log('🔍 Verifying email code for:', email);
916
- console.log('🔑 Code length:', code.length);
917
- console.log('🧪 Test mode:', testMode);
918
-
919
- if (!email || !email.includes('@')) {
920
- return {
921
- success: false,
922
- error: 'Valid email address is required',
923
- };
924
- }
925
863
 
926
- if (!code || code.length < 4) {
927
- return {
928
- success: false,
929
- error: 'Valid verification code is required',
930
- };
931
- }
932
-
933
- // In test mode, always return success with mock JWT token
934
- if (testMode) {
935
- console.log('🧪 Test mode: Always returning success with mock JWT token');
936
- const mockToken = 'test-jwt-token-' + Date.now();
864
+ const response = await makeDeveloperRequest('/email/verification', {
865
+ method: 'POST',
866
+ body: JSON.stringify({
867
+ email,
868
+ action: 'verify',
869
+ code,
870
+ testMode
871
+ })
872
+ });
873
+
874
+ const data = await response.json();
875
+
876
+ if (response.ok && data.success) {
877
+ console.log('✅ Email verification successful');
937
878
 
938
- // Store mock token for API requests
939
- await AsyncStorage.setItem('email_verification_token', mockToken);
940
- await AsyncStorage.setItem('onairos_jwt_token', mockToken);
941
- await AsyncStorage.setItem('email_verification_email', email);
879
+ // Store JWT token if received
880
+ if (data.token || data.jwtToken) {
881
+ const jwtToken = data.token || data.jwtToken;
882
+ await storeJWT(jwtToken);
883
+ console.log('🎫 JWT token stored successfully');
884
+ }
942
885
 
943
886
  return {
944
887
  success: true,
945
- message: 'Email verification successful (test mode)',
946
- existingUser: false,
947
- jwtToken: mockToken,
888
+ message: data.message || 'Email verified successfully',
889
+ existingUser: data.existingUser || false,
890
+ token: data.token || data.jwtToken
948
891
  };
949
- }
950
-
951
- // Production mode: Make real API call with API key authentication
952
- try {
953
- // 🔑 Ensure API key is initialized before making authenticated requests
954
- await ensureApiKeyInitialized();
955
-
956
- const response = await makeAuthenticatedRequest('/email/verification', {
957
- method: 'POST',
958
- body: JSON.stringify({
959
- email,
960
- code,
961
- action: 'verify',
962
- }),
963
- });
964
-
965
- const result = await response.json();
966
- console.log('📡 Email verification API response:', result);
967
-
968
- if (response.ok && result.success) {
969
- console.log('✅ Email verification successful');
970
-
971
- // 🎫 CRITICAL: Store JWT token from email verification response
972
- const jwtToken = result.token || result.jwtToken || result.jwt || result.authToken;
973
-
974
- if (jwtToken) {
975
- console.log('🎫 Storing JWT token from email verification response');
976
- await AsyncStorage.setItem('email_verification_token', jwtToken);
977
- await AsyncStorage.setItem('onairos_jwt_token', jwtToken);
978
- await AsyncStorage.setItem('enoch_token', jwtToken);
979
- await AsyncStorage.setItem('auth_token', jwtToken);
980
- await AsyncStorage.setItem('email_verification_email', email);
981
- await AsyncStorage.setItem('token_timestamp', Date.now().toString());
982
- } else {
983
- console.warn('⚠️ No JWT token received from email verification API');
984
- }
985
-
986
- return {
987
- success: true,
988
- message: result.message || 'Email verification successful',
989
- existingUser: result.existingUser || false,
990
- jwtToken: jwtToken,
991
- };
992
- } else {
993
- console.error('❌ Email verification failed:', result.error);
994
- return {
995
- success: false,
996
- error: result.error || 'Email verification failed',
997
- };
998
- }
999
- } catch (apiError) {
1000
- console.error('❌ Email verification API call failed:', apiError);
892
+ } else {
893
+ console.error('❌ Email verification failed:', data.error);
1001
894
  return {
1002
895
  success: false,
1003
- error: 'Network error during email verification',
896
+ error: data.error || 'Invalid verification code'
1004
897
  };
1005
898
  }
1006
899
  } catch (error) {
1007
- console.error('❌ Email verification error:', error);
900
+ console.error('❌ Error verifying email code:', error);
1008
901
  return {
1009
902
  success: false,
1010
- error: error instanceof Error ? error.message : 'Unknown error',
903
+ error: error instanceof Error ? error.message : 'Network error'
1011
904
  };
1012
905
  }
1013
906
  };
1014
907
 
1015
- export const checkEmailVerificationStatus = async (email: string, testMode = false): Promise<{
1016
- success: boolean;
1017
- isPending?: boolean;
1018
- message?: string;
1019
- error?: string;
1020
- }> => {
908
+ /**
909
+ * Check email verification status
910
+ * @param email Email address
911
+ * @param testMode Whether to use test mode
912
+ * @returns Promise with status result
913
+ */
914
+ export const checkEmailVerificationStatus = async (
915
+ email: string,
916
+ testMode: boolean = false
917
+ ): Promise<{ success: boolean; isPending?: boolean; error?: string }> => {
1021
918
  try {
1022
919
  console.log('🔍 Checking email verification status for:', email);
1023
- console.log('🔍 Test mode:', testMode);
1024
920
 
1025
- // In test mode, always return no pending verification
1026
- if (testMode) {
1027
- console.log('🧪 Test mode: Always returning no pending verification');
921
+ const response = await makeDeveloperRequest('/email/verification/status', {
922
+ method: 'POST',
923
+ body: JSON.stringify({
924
+ email,
925
+ testMode
926
+ })
927
+ });
928
+
929
+ const data = await response.json();
930
+
931
+ if (response.ok && data.success) {
1028
932
  return {
1029
933
  success: true,
1030
- isPending: false,
1031
- message: 'Status retrieved successfully (test mode)',
934
+ isPending: data.isPending || false
1032
935
  };
1033
- }
1034
-
1035
- // Production mode: Make real API call with API key authentication
1036
- try {
1037
- // 🔑 Ensure API key is initialized before making authenticated requests
1038
- await ensureApiKeyInitialized();
1039
-
1040
- const response = await makeAuthenticatedRequest(`/email/verify/status/${encodeURIComponent(email)}`, {
1041
- method: 'GET',
1042
- });
1043
-
1044
- const result = await response.json();
1045
- console.log('📡 Email verification status API response:', result);
1046
-
1047
- if (response.ok && result.success) {
1048
- console.log('✅ Email verification status retrieved');
1049
- return {
1050
- success: true,
1051
- isPending: result.isPending || false,
1052
- message: result.message || 'Status retrieved successfully',
1053
- };
1054
- } else {
1055
- console.error('❌ Email verification status failed:', result.error);
1056
- return {
1057
- success: false,
1058
- error: result.error || 'Failed to check verification status',
1059
- };
1060
- }
1061
- } catch (apiError) {
1062
- console.error('❌ Email verification status API call failed:', apiError);
936
+ } else {
1063
937
  return {
1064
938
  success: false,
1065
- error: 'Network error while checking status',
939
+ error: data.error || 'Failed to check verification status'
1066
940
  };
1067
941
  }
1068
942
  } catch (error) {
1069
- console.error('❌ Email verification status error:', error);
943
+ console.error('❌ Error checking email verification status:', error);
1070
944
  return {
1071
945
  success: false,
1072
- error: error instanceof Error ? error.message : 'Unknown error',
946
+ error: error instanceof Error ? error.message : 'Network error'
1073
947
  };
1074
948
  }
1075
949
  };
1076
950
 
1077
951
  /**
1078
- * 🔌 UNIVERSAL PLATFORM DISCONNECTION
1079
- * Backend confirmed this endpoint is fully implemented
952
+ * Disconnect a platform (uses developer API key)
953
+ * @param platform Platform to disconnect
954
+ * @param username Username associated with the platform
955
+ * @returns Promise with disconnect result
1080
956
  */
1081
- export const disconnectPlatform = async (platform: string, username: string): Promise<{
1082
- success: boolean;
1083
- message?: string;
1084
- error?: string;
1085
- }> => {
957
+ export const disconnectPlatform = async (platform: string, username: string): Promise<{ success: boolean; error?: string }> => {
1086
958
  try {
1087
959
  console.log('🔌 Disconnecting platform:', platform, 'for user:', username);
1088
960
 
1089
- if (!platform || !username) {
1090
- return {
1091
- success: false,
1092
- error: 'Platform and username are required',
1093
- };
1094
- }
1095
-
1096
961
  // Make authenticated API call to disconnect platform
1097
- const response = await makeAuthenticatedRequest('/revoke', {
962
+ const response = await makeDeveloperRequest('/revoke', {
1098
963
  method: 'POST',
1099
964
  body: JSON.stringify({
1100
965
  platform,
1101
- username,
1102
- }),
966
+ username
967
+ })
1103
968
  });
1104
-
1105
- const result = await response.json();
1106
- console.log('📡 Platform disconnect API response:', result);
1107
-
1108
- if (response.ok && result.success) {
1109
- console.log('✅ Platform disconnected successfully');
1110
- return {
1111
- success: true,
1112
- message: result.message || 'Platform disconnected successfully',
1113
- };
969
+
970
+ const data = await response.json();
971
+
972
+ if (response.ok && data.success) {
973
+ console.log(`✅ ${platform} disconnected successfully`);
974
+ return { success: true };
1114
975
  } else {
1115
- console.error('❌ Platform disconnect failed:', result.error);
976
+ console.error(`❌ Failed to disconnect ${platform}:`, data.error);
1116
977
  return {
1117
978
  success: false,
1118
- error: result.error || 'Failed to disconnect platform',
979
+ error: data.error || 'Failed to disconnect platform'
1119
980
  };
1120
981
  }
1121
982
  } catch (error) {
1122
- console.error('❌ Platform disconnect error:', error);
983
+ console.error(`❌ Error disconnecting ${platform}:`, error);
1123
984
  return {
1124
985
  success: false,
1125
- error: error instanceof Error ? error.message : 'Platform disconnect failed',
986
+ error: error instanceof Error ? error.message : 'Network error'
1126
987
  };
1127
988
  }
1128
989
  };
1129
990
 
1130
991
  /**
1131
- * 🔐 STORE PIN AFTER BIOMETRIC AUTHENTICATION
1132
- * Send PIN separately to /store-pin/web endpoint after biometric Face ID verification
992
+ * Store PIN for user (uses developer API key for now, should be JWT in future)
993
+ * @param username Username
994
+ * @param pin User PIN
995
+ * @returns Promise with result
1133
996
  */
1134
- export const storePinAfterBiometric = async (username: string, pin: string, jwtToken?: string): Promise<{
1135
- success: boolean;
1136
- message?: string;
1137
- error?: string;
1138
- }> => {
997
+ export const storePIN = async (username: string, pin: string): Promise<{ success: boolean; error?: string }> => {
1139
998
  try {
1140
- console.log('🔐 Storing PIN after biometric authentication for user:', username);
1141
- console.log('🔑 PIN length:', pin.length);
1142
- console.log('🎫 JWT token provided:', !!jwtToken);
1143
-
1144
- if (!username || !pin) {
1145
- return {
1146
- success: false,
1147
- error: 'Username and PIN are required',
1148
- };
1149
- }
1150
-
1151
- if (pin.length < 4) {
1152
- return {
1153
- success: false,
1154
- error: 'PIN must be at least 4 digits',
1155
- };
1156
- }
1157
-
1158
- // Get JWT token from storage if not provided
1159
- let authToken = jwtToken;
1160
- if (!authToken) {
1161
- authToken = await AsyncStorage.getItem('onairos_jwt_token') ||
1162
- await AsyncStorage.getItem('enoch_token') ||
1163
- await AsyncStorage.getItem('auth_token') ||
1164
- await AsyncStorage.getItem('email_verification_token');
1165
- }
1166
-
1167
- if (!authToken) {
1168
- console.warn('⚠️ No JWT token available for PIN storage');
1169
- return {
1170
- success: false,
1171
- error: 'No authentication token available',
1172
- };
1173
- }
1174
-
1175
- console.log('📤 Sending PIN to /store-pin/web endpoint');
999
+ console.log('🔐 Storing PIN for user:', username);
1176
1000
 
1177
1001
  // Make authenticated request to store PIN
1178
- const response = await makeAuthenticatedRequest('/store-pin/web', {
1002
+ const response = await makeDeveloperRequest('/store-pin/web', {
1179
1003
  method: 'POST',
1180
1004
  headers: {
1181
- 'Authorization': `Bearer ${authToken}`,
1005
+ 'Content-Type': 'application/json',
1182
1006
  },
1183
1007
  body: JSON.stringify({
1184
1008
  username,
1185
- pin,
1186
- }),
1009
+ pin
1010
+ })
1187
1011
  });
1188
-
1189
- console.log('📡 PIN storage response status:', response.status);
1190
-
1191
- if (!response.ok) {
1192
- const errorText = await response.text();
1193
- console.error('❌ PIN storage failed:', errorText);
1194
- return {
1195
- success: false,
1196
- error: `PIN storage failed: ${response.status} - ${errorText}`,
1197
- };
1198
- }
1199
-
1200
- const result = await response.json();
1201
- console.log('📥 PIN storage response:', result);
1202
-
1203
- if (result.success) {
1204
- console.log('✅ PIN stored successfully after biometric authentication');
1205
-
1206
- // Store PIN locally for future use
1207
- await AsyncStorage.setItem('user_pin_stored', 'true');
1208
- await AsyncStorage.setItem('pin_storage_timestamp', Date.now().toString());
1209
-
1210
- return {
1211
- success: true,
1212
- message: result.message || 'PIN stored successfully',
1213
- };
1012
+
1013
+ const data = await response.json();
1014
+
1015
+ if (response.ok && data.success) {
1016
+ console.log('✅ PIN stored successfully');
1017
+ return { success: true };
1214
1018
  } else {
1215
- console.error('❌ PIN storage API returned error:', result.error);
1019
+ console.error('❌ Failed to store PIN:', data.error);
1216
1020
  return {
1217
1021
  success: false,
1218
- error: result.error || 'PIN storage failed',
1022
+ error: data.error || 'Failed to store PIN'
1219
1023
  };
1220
1024
  }
1221
1025
  } catch (error) {
1222
- console.error('❌ Error storing PIN after biometric authentication:', error);
1026
+ console.error('❌ Error storing PIN:', error);
1223
1027
  return {
1224
1028
  success: false,
1225
- error: error instanceof Error ? error.message : 'PIN storage failed',
1029
+ error: error instanceof Error ? error.message : 'Network error'
1226
1030
  };
1227
1031
  }
1228
1032
  };