248 lines
8.3 KiB
TypeScript
248 lines
8.3 KiB
TypeScript
/**
|
|
* Cookie Utilities
|
|
* Handles cookie management for WebView authentication
|
|
*/
|
|
|
|
import CookieManager from '@react-native-cookies/cookies';
|
|
import { Platform } from 'react-native';
|
|
import { ALLOWED_DOMAIN, COOKIE_REFRESH_INTERVAL, INITIAL_COOKIE_DELAY } from './constants';
|
|
|
|
/**
|
|
* Interface for cookie data
|
|
*/
|
|
export interface CookieData {
|
|
[key: string]: any;
|
|
}
|
|
|
|
/**
|
|
* Cookie Handler Class
|
|
*/
|
|
export class CookieHandler {
|
|
private setWebViewCookies: (cookies: string | null) => void;
|
|
|
|
constructor(setWebViewCookies: (cookies: string | null) => void) {
|
|
this.setWebViewCookies = setWebViewCookies;
|
|
}
|
|
|
|
/**
|
|
* Get WebView cookies for authentication
|
|
* @returns Promise<string | null> - Cookie string or null if not found
|
|
*/
|
|
async getWebViewCookies(): Promise<string | null> {
|
|
try {
|
|
console.log('🍪 Requesting cookies using @react-native-cookies/cookies...');
|
|
|
|
const baseUrl = `${ALLOWED_DOMAIN}`;
|
|
console.log('🍪 Getting cookies for URL:', baseUrl);
|
|
|
|
let cookieString = '';
|
|
|
|
// Platform-specific cookie handling
|
|
if (Platform.OS === 'ios') {
|
|
// iOS: Can use getAll()
|
|
try {
|
|
const cookies = await CookieManager.getAll();
|
|
console.log('🍪 iOS - All cookies retrieved:', cookies);
|
|
|
|
// Filter cookies for our domain
|
|
const domainCookies = Object.keys(cookies).filter(key =>
|
|
key.includes(baseUrl) || key.includes(ALLOWED_DOMAIN.replace('/', ''))
|
|
);
|
|
|
|
console.log('🍪 iOS - Domain cookies found:', domainCookies);
|
|
|
|
for (const cookieKey of domainCookies) {
|
|
const cookie = cookies[cookieKey];
|
|
console.log('🍪 iOS - Checking cookie:', cookieKey, cookie);
|
|
|
|
if (cookie && typeof cookie === 'object') {
|
|
const cookieValue = cookie.value || cookie;
|
|
if (cookieValue && typeof cookieValue === 'string' && cookieValue.includes('session_id=')) {
|
|
const sessionMatch = cookieValue.match(/session_id=([^;]+)/);
|
|
if (sessionMatch) {
|
|
console.log('✅ iOS - Found session_id in cookie:', sessionMatch[1]);
|
|
}
|
|
}
|
|
|
|
if (typeof cookie === 'object' && cookie.name && cookie.value) {
|
|
cookieString += `${cookie.name}=${cookie.value}; `;
|
|
} else if (typeof cookie === 'string') {
|
|
cookieString += cookie + '; ';
|
|
}
|
|
}
|
|
}
|
|
} catch (iosError) {
|
|
console.log('⚠️ iOS getAll() failed, trying direct method:', iosError);
|
|
}
|
|
}
|
|
|
|
// Both platforms: Try getting cookies directly for the domain
|
|
try {
|
|
console.log('🍪 Getting direct cookies for domain:', baseUrl);
|
|
const directCookies = await CookieManager.get(baseUrl);
|
|
console.log('🍪 Direct cookies for domain:', directCookies);
|
|
|
|
if (directCookies && Object.keys(directCookies).length > 0) {
|
|
// Convert to cookie string format
|
|
const directCookieString = Object.entries(directCookies)
|
|
.map(([name, value]) => `${name}=${value}`)
|
|
.join('; ');
|
|
|
|
console.log('🍪 Direct cookie string:', directCookieString);
|
|
|
|
if (directCookieString && directCookieString.includes('session_id')) {
|
|
cookieString = directCookieString;
|
|
console.log('✅ Found session_id in direct cookies:', cookieString);
|
|
} else {
|
|
console.warn('⚠️ Direct cookies found but no session_id:', directCookieString);
|
|
}
|
|
} else {
|
|
console.warn('⚠️ No direct cookies found for domain');
|
|
}
|
|
} catch (directError) {
|
|
console.log('⚠️ Could not get direct cookies:', directError);
|
|
}
|
|
|
|
// Fallback: Try getting cookies for the WebView URL
|
|
try {
|
|
const webViewUrl = `${ALLOWED_DOMAIN}/web`;
|
|
console.log('🍪 Fallback - Getting cookies for WebView URL:', webViewUrl);
|
|
const webViewCookies = await CookieManager.get(webViewUrl);
|
|
console.log('🍪 WebView cookies:', webViewCookies);
|
|
|
|
if (webViewCookies && Object.keys(webViewCookies).length > 0) {
|
|
const webViewCookieString = Object.entries(webViewCookies)
|
|
.map(([name, value]) => `${name}=${value}`)
|
|
.join('; ');
|
|
|
|
if (webViewCookieString && webViewCookieString.includes('session_id')) {
|
|
cookieString = webViewCookieString;
|
|
console.log('✅ Found session_id in WebView cookies:', cookieString);
|
|
}
|
|
}
|
|
} catch (webViewError) {
|
|
console.log('⚠️ Could not get WebView cookies:', webViewError);
|
|
}
|
|
|
|
if (cookieString && cookieString.includes('session_id')) {
|
|
console.log('✅ Valid session cookies found:', cookieString);
|
|
this.setWebViewCookies(cookieString);
|
|
return cookieString;
|
|
} else {
|
|
console.warn('⚠️ No session_id found in any cookie method');
|
|
console.warn('⚠️ Final cookie string:', cookieString);
|
|
this.setWebViewCookies(null);
|
|
return null;
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Error getting cookies with @react-native-cookies/cookies:', error);
|
|
this.setWebViewCookies(null);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh WebView cookies periodically
|
|
* @returns Function to clear the interval
|
|
*/
|
|
refreshWebViewCookies(): () => void {
|
|
// Initial cookie request after a longer delay to ensure WebView is fully loaded and user is logged in
|
|
setTimeout(() => {
|
|
console.log('🔄 Initial cookie refresh after WebView load');
|
|
this.getWebViewCookies();
|
|
}, INITIAL_COOKIE_DELAY);
|
|
|
|
// Set up periodic cookie refresh
|
|
const cookieRefreshInterval = setInterval(() => {
|
|
console.log('🔄 Periodic cookie refresh');
|
|
this.getWebViewCookies();
|
|
}, COOKIE_REFRESH_INTERVAL);
|
|
|
|
// Return cleanup function
|
|
return () => clearInterval(cookieRefreshInterval);
|
|
}
|
|
|
|
/**
|
|
* Get cookies for a specific URL
|
|
* @param url - URL to get cookies for
|
|
* @returns Promise<CookieData | null> - Cookie data or null
|
|
*/
|
|
async getCookiesForUrl(url: string): Promise<CookieData | null> {
|
|
try {
|
|
console.log('🍪 Getting cookies for URL:', url);
|
|
const cookies = await CookieManager.get(url);
|
|
console.log('🍪 Cookies for URL:', cookies);
|
|
return cookies;
|
|
} catch (error) {
|
|
console.error('❌ Error getting cookies for URL:', url, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set cookies for a specific URL
|
|
* @param url - URL to set cookies for
|
|
* @param cookies - Cookie data to set
|
|
* @returns Promise<boolean> - Success status
|
|
*/
|
|
async setCookiesForUrl(url: string, cookies: any): Promise<boolean> {
|
|
try {
|
|
console.log('🍪 Setting cookies for URL:', url, cookies);
|
|
await CookieManager.set(url, cookies);
|
|
console.log('✅ Cookies set successfully for URL:', url);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('❌ Error setting cookies for URL:', url, error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all cookies
|
|
* @returns Promise<boolean> - Success status
|
|
*/
|
|
async clearAllCookies(): Promise<boolean> {
|
|
try {
|
|
console.log('🍪 Clearing all cookies');
|
|
await CookieManager.clearAll();
|
|
console.log('✅ All cookies cleared successfully');
|
|
this.setWebViewCookies(null);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('❌ Error clearing cookies:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if session cookies are valid
|
|
* @param cookies - Cookie string to validate
|
|
* @returns boolean - Whether cookies are valid
|
|
*/
|
|
isValidSessionCookie(cookies: string | null): boolean {
|
|
if (!cookies) {
|
|
return false;
|
|
}
|
|
|
|
const hasSessionId = cookies.includes('session_id=');
|
|
const hasValidFormat = cookies.includes('=') && cookies.includes(';');
|
|
|
|
console.log('🍪 Cookie validation:', {
|
|
hasSessionId,
|
|
hasValidFormat,
|
|
cookieLength: cookies.length
|
|
});
|
|
|
|
return hasSessionId && hasValidFormat;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create cookie handler instance
|
|
*/
|
|
export function createCookieHandler(
|
|
setWebViewCookies: (cookies: string | null) => void
|
|
): CookieHandler {
|
|
return new CookieHandler(setWebViewCookies);
|
|
}
|