Spaces:
Paused
Paused
Download src/services/auth-service.js from Luca448/APP-Backend: direct link, hf CLI and curl.
- Browser
- Download file 3.23 kB
-
https://huggingface.co/spaces/Luca448/APP-Backend/resolve/main/src/services/auth-service.js
- Command line
-
hf download hf://spaces/Luca448/APP-Backend/src/services/auth-service.js
-
curl -L -o auth-service.js https://huggingface.co/spaces/Luca448/APP-Backend/resolve/main/src/services/auth-service.js
3.23 kB
| import { supabase } from './supabase-client.js'; | |
| import { cryptoService } from './crypto-service.js'; | |
| import { db } from '../db/database.js'; | |
| class AuthService { | |
| constructor() { | |
| this.user = null; | |
| this.session = null; | |
| this.onAuthStateChangeCallbacks = []; | |
| // Auto-setup auth listener | |
| supabase.auth.onAuthStateChange((event, session) => { | |
| this.session = session; | |
| this.user = session?.user || null; | |
| // If we log out, clear the crypto key | |
| if (event === 'SIGNED_OUT') { | |
| cryptoService.clearKey(); | |
| } | |
| this.notifyListeners(event, session); | |
| }); | |
| } | |
| async initialize() { | |
| const { data, error } = await supabase.auth.getSession(); | |
| if (data.session) { | |
| this.session = data.session; | |
| this.user = data.session.user; | |
| // We have a session, but we don't have the crypto key! | |
| // If the crypto key is null, the UI should prompt the user to "Unlock" their data | |
| // by entering their password again, OR we can try to store the derived key in sessionStorage | |
| // (not localStorage!) so it survives page reloads but dies when the tab closes. | |
| const restored = await cryptoService.restoreKey(); | |
| if (!restored) { | |
| // App will need to ask for password to unlock | |
| console.warn('Session active, but crypto key missing. Needs unlock.'); | |
| } | |
| } | |
| return { user: this.user, session: this.session }; | |
| } | |
| onAuthStateChange(callback) { | |
| this.onAuthStateChangeCallbacks.push(callback); | |
| } | |
| notifyListeners(event, session) { | |
| this.onAuthStateChangeCallbacks.forEach(cb => cb(event, session)); | |
| } | |
| async signUp(email, password) { | |
| // 1. Derive encryption key from password BEFORE signing up | |
| await cryptoService.deriveKey(password, email); | |
| sessionStorage.setItem('schoolmind_temp_key_marker', 'true'); | |
| // 2. Sign up with Supabase | |
| const { data, error } = await supabase.auth.signUp({ | |
| email, | |
| password, | |
| }); | |
| if (error) { | |
| cryptoService.clearKey(); | |
| sessionStorage.removeItem('schoolmind_temp_key_marker'); | |
| throw error; | |
| } | |
| return data; | |
| } | |
| async signIn(email, password) { | |
| // 1. Derive encryption key from password | |
| await cryptoService.deriveKey(password, email); | |
| sessionStorage.setItem('schoolmind_temp_key_marker', 'true'); | |
| // 2. Sign in with Supabase | |
| const { data, error } = await supabase.auth.signInWithPassword({ | |
| email, | |
| password, | |
| }); | |
| if (error) { | |
| cryptoService.clearKey(); | |
| sessionStorage.removeItem('schoolmind_temp_key_marker'); | |
| throw error; | |
| } | |
| return data; | |
| } | |
| async unlockCrypto(email, password) { | |
| // Used when returning to an already active session, to just derive the key | |
| await cryptoService.deriveKey(password, email); | |
| sessionStorage.setItem('schoolmind_temp_key_marker', 'true'); | |
| return true; | |
| } | |
| async signOut() { | |
| const { error } = await supabase.auth.signOut(); | |
| cryptoService.clearKey(); | |
| sessionStorage.removeItem('schoolmind_temp_key_marker'); | |
| if (error) throw error; | |
| } | |
| isCryptoUnlocked() { | |
| return cryptoService.key !== null; | |
| } | |
| } | |
| export const authService = new AuthService(); | |