| import cacheService from './cacheService'; |
|
|
| class CookieService { |
| |
| |
| |
| |
| |
| |
| |
| async set(name, value, options = {}) { |
| |
| const isProduction = import.meta.env.VITE_NODE_ENV === 'production'; |
| const cacheOptions = { |
| httpOnly: true, |
| secure: true, |
| sameSite: isProduction ? 'Lax' : 'Strict', |
| ...options |
| }; |
| |
| |
| let ttl = 60 * 60 * 1000; |
| if (options.expires) { |
| ttl = options.expires.getTime() - Date.now(); |
| } else if (options.maxAge) { |
| ttl = options.maxAge * 1000; |
| } |
| |
| await cacheService.set(`cookie_${name}`, { value, options }, ttl); |
| |
| |
| |
| const cookieData = { |
| value, |
| options: { |
| secure: cacheOptions.secure, |
| sameSite: cacheOptions.sameSite, |
| expires: options.expires?.toISOString() || null, |
| maxAge: options.maxAge || null |
| } |
| }; |
| |
| try { |
| localStorage.setItem(`__secure_cookie_${name}`, JSON.stringify(cookieData)); |
| if (import.meta.env.VITE_NODE_ENV === 'development') { |
| console.log(`πͺ [Cookie] Set secure cookie: ${name}`); |
| } |
| } catch (error) { |
| console.warn(`πͺ [Cookie] Could not set localStorage cookie: ${name}`, error); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| async get(name) { |
| |
| const cached = await cacheService.get(`cookie_${name}`); |
| if (cached) { |
| return cached.value; |
| } |
| |
| |
| try { |
| const cookieData = localStorage.getItem(`__secure_cookie_${name}`); |
| if (cookieData) { |
| const parsed = JSON.parse(cookieData); |
| |
| if (parsed.options.expires) { |
| const expiry = new Date(parsed.options.expires); |
| if (Date.now() > expiry.getTime()) { |
| await this.remove(name); |
| return null; |
| } |
| } |
| return parsed.value; |
| } |
| } catch (error) { |
| console.warn(`πͺ [Cookie] Could not read localStorage cookie: ${name}`, error); |
| } |
| |
| return null; |
| } |
|
|
| |
| |
| |
| |
| |
| async remove(name) { |
| |
| await cacheService.remove(`cookie_${name}`); |
| |
| |
| try { |
| localStorage.removeItem(`__secure_cookie_${name}`); |
| if (import.meta.env.VITE_NODE_ENV === 'development') { |
| console.log(`πͺ [Cookie] Removed cookie: ${name}`); |
| } |
| } catch (error) { |
| console.warn(`πͺ [Cookie] Could not remove localStorage cookie: ${name}`, error); |
| } |
| } |
|
|
| |
| |
| |
| |
| async clear() { |
| |
| const keys = (await cacheService.storage.keys()) || []; |
| const cookieKeys = keys.filter(key => key.startsWith('cookie_')); |
| await Promise.all(cookieKeys.map(key => cacheService.remove(key))); |
| |
| |
| try { |
| const localStorageKeys = Object.keys(localStorage); |
| const cookieLocalStorageKeys = localStorageKeys.filter(key => key.startsWith('__secure_cookie_')); |
| cookieLocalStorageKeys.forEach(key => localStorage.removeItem(key)); |
| |
| if (import.meta.env.VITE_NODE_ENV === 'development') { |
| console.log('πͺ [Cookie] Cleared all cookies'); |
| } |
| } catch (error) { |
| console.warn('πͺ [Cookie] Could not clear all localStorage cookies', error); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| async exists(name) { |
| return (await this.get(name)) !== null; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| async setAuthTokens(accessToken, rememberMe = false) { |
| const now = new Date(); |
| let accessTokenExpiry; |
| |
| if (rememberMe) { |
| |
| accessTokenExpiry = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); |
| } else { |
| |
| accessTokenExpiry = new Date(now.getTime() + 60 * 60 * 1000); |
| } |
| |
| |
| await this.set('access_token', accessToken, { |
| expires: accessTokenExpiry, |
| secure: true, |
| sameSite: import.meta.env.VITE_NODE_ENV === 'production' ? 'Lax' : 'Strict' |
| }); |
| |
| |
| await this.set('remember_me', rememberMe.toString(), { |
| expires: accessTokenExpiry, |
| secure: true, |
| sameSite: import.meta.env.VITE_NODE_ENV === 'production' ? 'Lax' : 'Strict' |
| }); |
| |
| if (import.meta.env.VITE_NODE_ENV === 'development') { |
| console.log('πͺ [Cookie] Set auth tokens with rememberMe:', rememberMe); |
| } |
| } |
|
|
| |
| |
| |
| |
| async getAuthTokens() { |
| try { |
| const [accessToken, rememberMe] = await Promise.all([ |
| this.get('access_token'), |
| this.get('remember_me') |
| ]); |
| |
| if (!accessToken) { |
| return null; |
| } |
| |
| return { |
| accessToken, |
| rememberMe: rememberMe === 'true' |
| }; |
| } catch (error) { |
| console.error('πͺ [Cookie] Error getting auth tokens', error); |
| return null; |
| } |
| } |
|
|
| |
| |
| |
| |
| async clearAuthTokens() { |
| await Promise.all([ |
| this.remove('access_token'), |
| this.remove('remember_me') |
| ]); |
| |
| if (import.meta.env.VITE_NODE_ENV === 'development') { |
| console.log('πͺ [Cookie] Cleared auth tokens'); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| async refreshAuthTokens(newAccessToken, rememberMe = false) { |
| await this.clearAuthTokens(); |
| await this.setAuthTokens(newAccessToken, rememberMe); |
| } |
| } |
|
|
| |
| export default new CookieService(); |