Files
wallabicher/web/dashboard/src/services/auth.js
Omar Sánchez Pizarro 6ec8855c00 add landing and subscription plans
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2026-01-20 23:49:19 +01:00

231 lines
5.6 KiB
JavaScript

// Servicio de autenticación para gestionar tokens
import { getDeviceFingerprint } from './fingerprint.js';
const AUTH_STORAGE_KEY = 'wallabicher_token';
const USERNAME_STORAGE_KEY = 'wallabicher_username';
const ROLE_STORAGE_KEY = 'wallabicher_role';
class AuthService {
constructor() {
this.token = this.loadToken();
this.username = this.loadUsername();
this.role = this.loadRole();
}
// Cargar token desde localStorage
loadToken() {
try {
return localStorage.getItem(AUTH_STORAGE_KEY) || '';
} catch (error) {
console.error('Error cargando token:', error);
return '';
}
}
// Cargar username desde localStorage
loadUsername() {
try {
return localStorage.getItem(USERNAME_STORAGE_KEY) || '';
} catch (error) {
console.error('Error cargando username:', error);
return '';
}
}
// Guardar token, username y role en localStorage
saveSession(token, username, role = 'user') {
try {
this.token = token;
this.username = username;
this.role = role;
localStorage.setItem(AUTH_STORAGE_KEY, token);
localStorage.setItem(USERNAME_STORAGE_KEY, username);
localStorage.setItem(ROLE_STORAGE_KEY, role);
return true;
} catch (error) {
console.error('Error guardando sesión:', error);
return false;
}
}
// Cargar role desde localStorage
loadRole() {
try {
return localStorage.getItem(ROLE_STORAGE_KEY) || 'user';
} catch (error) {
console.error('Error cargando role:', error);
return 'user';
}
}
// Eliminar token, username y role
clearSession() {
try {
this.token = '';
this.username = '';
this.role = 'user';
localStorage.removeItem(AUTH_STORAGE_KEY);
localStorage.removeItem(USERNAME_STORAGE_KEY);
localStorage.removeItem(ROLE_STORAGE_KEY);
return true;
} catch (error) {
console.error('Error eliminando sesión:', error);
return false;
}
}
// Obtener token actual
getToken() {
return this.token;
}
// Obtener username actual
getUsername() {
return this.username;
}
// Obtener role actual
getRole() {
return this.role;
}
// Verificar si es admin
isAdmin() {
return this.role === 'admin';
}
// Verificar si hay sesión activa (token guardado)
hasCredentials() {
return !!this.token;
}
// Generar header de autenticación Bearer
getAuthHeader() {
if (!this.token) {
return null;
}
return `Bearer ${this.token}`;
}
// Hacer login (llamar al endpoint de login)
async login(username, password) {
try {
// Obtener fingerprint del dispositivo
let fingerprintData = null;
try {
fingerprintData = await getDeviceFingerprint();
} catch (error) {
console.warn('Error obteniendo fingerprint, continuando sin él:', error);
}
const requestBody = {
username,
password,
};
// Agregar fingerprint si está disponible
if (fingerprintData) {
requestBody.fingerprint = fingerprintData.fingerprint;
requestBody.deviceInfo = fingerprintData.deviceInfo;
}
const response = await fetch('/api/users/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'Error en login');
}
if (data.success && data.token) {
const role = data.role || 'user';
this.saveSession(data.token, data.username, role);
return { success: true, token: data.token, username: data.username, role };
}
throw new Error('Respuesta inválida del servidor');
} catch (error) {
console.error('Error en login:', error);
throw error;
}
}
// Hacer logout (llamar al endpoint de logout)
async logout() {
try {
const token = this.token;
if (token) {
try {
await fetch('/api/users/logout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
} catch (error) {
// Si falla el logout en el servidor, aún así limpiar localmente
console.error('Error al cerrar sesión en el servidor:', error);
}
}
this.clearSession();
return true;
} catch (error) {
console.error('Error en logout:', error);
this.clearSession(); // Limpiar localmente de todas formas
return false;
}
}
// Verificar si el token sigue siendo válido
async validateSession() {
if (!this.token) {
return false;
}
try {
const response = await fetch('/api/users/me', {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.token}`,
},
});
if (response.ok) {
const data = await response.json();
if (data.success && data.authenticated) {
// Actualizar role si está disponible
if (data.role) {
this.role = data.role;
localStorage.setItem(ROLE_STORAGE_KEY, data.role);
}
return true;
}
}
// Si el token es inválido, limpiar sesión
if (response.status === 401) {
this.clearSession();
}
return false;
} catch (error) {
console.error('Error validando sesión:', error);
return false;
}
}
}
// Exportar instancia singleton
const authService = new AuthService();
export default authService;