T4B_Chat/utilities/cookieUtils.ts

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);
}