2026-03-27 17:49:10 +01:00
|
|
|
const SUPABASE_URL = 'https://hwithddwaapyhnfwcesj.supabase.co';
|
|
|
|
|
const SUPABASE_ANON_KEY = 'sb_publishable_fGXkh0bSrAOqSk2jWKAzSg_NJD9YPCv';
|
|
|
|
|
const SESSION_KEY = 'craze_auth_session';
|
|
|
|
|
|
|
|
|
|
export interface AuthSession {
|
|
|
|
|
access_token: string;
|
2026-04-23 12:37:04 +02:00
|
|
|
refresh_token: string;
|
2026-03-27 17:49:10 +01:00
|
|
|
user: { id: string; email: string };
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 17:54:31 +01:00
|
|
|
export async function signUp(email: string, password: string): Promise<void> {
|
|
|
|
|
const response = await fetch(`${SUPABASE_URL}/auth/v1/signup`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'apikey': SUPABASE_ANON_KEY,
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({ email, password }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const err = await response.json().catch(() => ({}));
|
|
|
|
|
throw new Error(err.error_description || err.message || 'Registration failed.');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 17:49:10 +01:00
|
|
|
export async function signIn(email: string, password: string): Promise<AuthSession> {
|
|
|
|
|
const response = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'apikey': SUPABASE_ANON_KEY,
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({ email, password }),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
const err = await response.json().catch(() => ({}));
|
|
|
|
|
throw new Error(err.error_description || err.message || 'Invalid email or password.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await response.json();
|
2026-05-20 13:33:37 +02:00
|
|
|
|
|
|
|
|
// Validate status before signing in
|
|
|
|
|
try {
|
|
|
|
|
const statusRes = await fetch('/api/users-admin', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'Authorization': `Bearer ${data.access_token}`
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({ action: 'check-status' })
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!statusRes.ok) {
|
|
|
|
|
const err = await statusRes.json().catch(() => ({}));
|
|
|
|
|
throw new Error(err.error || 'Failed to verify account validation status.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const statusData = await statusRes.json();
|
|
|
|
|
if (!statusData.validated) {
|
|
|
|
|
throw new Error('Tu usuario aún no ha sido validado por un administrador.');
|
|
|
|
|
}
|
|
|
|
|
} catch (err: any) {
|
|
|
|
|
throw new Error(err.message || 'Error de validación del usuario.');
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 17:49:10 +01:00
|
|
|
const session: AuthSession = {
|
|
|
|
|
access_token: data.access_token,
|
2026-04-23 12:37:04 +02:00
|
|
|
refresh_token: data.refresh_token,
|
|
|
|
|
user: { id: data.user.id, email: data.user.email },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
localStorage.setItem(SESSION_KEY, JSON.stringify(session));
|
2026-05-26 12:49:22 +02:00
|
|
|
window.dispatchEvent(new Event('session-refreshed'));
|
2026-04-23 12:37:04 +02:00
|
|
|
return session;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-26 12:49:22 +02:00
|
|
|
let activeRefreshPromise: Promise<AuthSession> | null = null;
|
2026-04-23 12:37:04 +02:00
|
|
|
|
2026-05-26 12:49:22 +02:00
|
|
|
export async function refreshSession(refreshToken: string): Promise<AuthSession> {
|
|
|
|
|
if (activeRefreshPromise) {
|
|
|
|
|
return activeRefreshPromise;
|
2026-04-23 12:37:04 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-26 12:49:22 +02:00
|
|
|
activeRefreshPromise = (async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=refresh_token`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'apikey': SUPABASE_ANON_KEY,
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
|
|
|
});
|
2026-03-27 17:49:10 +01:00
|
|
|
|
2026-05-26 12:49:22 +02:00
|
|
|
if (!response.ok) {
|
|
|
|
|
if (response.status === 400 || response.status === 401 || response.status === 403) {
|
|
|
|
|
localStorage.removeItem(SESSION_KEY);
|
|
|
|
|
window.dispatchEvent(new Event('session-refreshed'));
|
|
|
|
|
throw new Error('Session expired. Please sign in again.');
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error(`Server error (${response.status}). Please try again later.`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
const session: AuthSession = {
|
|
|
|
|
access_token: data.access_token,
|
|
|
|
|
refresh_token: data.refresh_token,
|
|
|
|
|
user: { id: data.user.id, email: data.user.email },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
localStorage.setItem(SESSION_KEY, JSON.stringify(session));
|
|
|
|
|
window.dispatchEvent(new Event('session-refreshed'));
|
|
|
|
|
return session;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// If the error was not already thrown as "Session expired", we just propagate it.
|
|
|
|
|
throw error;
|
|
|
|
|
} finally {
|
|
|
|
|
activeRefreshPromise = null;
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
return activeRefreshPromise;
|
2026-03-27 17:49:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function signOut(): void {
|
|
|
|
|
localStorage.removeItem(SESSION_KEY);
|
2026-05-26 12:49:22 +02:00
|
|
|
window.dispatchEvent(new Event('session-refreshed'));
|
2026-03-27 17:49:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getStoredSession(): AuthSession | null {
|
|
|
|
|
try {
|
|
|
|
|
const raw = localStorage.getItem(SESSION_KEY);
|
|
|
|
|
return raw ? (JSON.parse(raw) as AuthSession) : null;
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|