main
js 99 lines 3.11 KB
Raw
1 /**
2 * MAPS Connect - Autenticación y sesión
3 */
4
5 const Auth = {
6 TOKEN_KEY: 'token',
7 USER_KEY: 'user',
8
9 saveSession(token, user) {
10 localStorage.setItem(this.TOKEN_KEY, token);
11 localStorage.setItem(this.USER_KEY, JSON.stringify(user));
12 },
13
14 getToken() {
15 return localStorage.getItem(this.TOKEN_KEY);
16 },
17
18 getUser() {
19 const user = localStorage.getItem(this.USER_KEY);
20 return user ? JSON.parse(user) : null;
21 },
22
23 /** Actualiza la foto del usuario en la sesión local (nuevaFoto null = eliminar). */
24 foto(nuevaFoto) {
25 const user = this.getUser();
26 if (!user) return;
27 user.foto = nuevaFoto || null;
28 localStorage.setItem(this.USER_KEY, JSON.stringify(user));
29 },
30
31 /** Actualiza campos del usuario en la sesión local (p. ej. nombre). */
32 actualizar(patch) {
33 const user = this.getUser();
34 if (!user) return;
35 Object.assign(user, patch);
36 localStorage.setItem(this.USER_KEY, JSON.stringify(user));
37 },
38
39 isAuthenticated() {
40 return !!this.getToken();
41 },
42
43 logout() {
44 localStorage.removeItem(this.TOKEN_KEY);
45 localStorage.removeItem(this.USER_KEY);
46 window.location.href = Auth.resolvePath('index.html');
47 },
48
49 /** Redirige a login si no hay sesión. Usar en páginas protegidas. */
50 requireAuth() {
51 if (!this.isAuthenticated()) {
52 window.location.href = this.resolvePath('login.html');
53 return false;
54 }
55 return true;
56 },
57
58 /** Valida la sesión contra el servidor y redirige al dashboard si es válida.
59 * Usar en login/registro: evita el bucle con tokens viejos o expirados. */
60 async redirectIfAuthenticated() {
61 if (!this.isAuthenticated()) return false;
62 try {
63 await API.request('/auth/perfil-estado');
64 window.location.href = this.resolvePath('pages/inicio.html');
65 return true;
66 } catch (e) {
67 // Token inválido o expirado: se limpia la sesión y se deja ver el login.
68 localStorage.removeItem(this.TOKEN_KEY);
69 localStorage.removeItem(this.USER_KEY);
70 return false;
71 }
72 },
73
74 /** Si el perfil está incompleto, lleva al usuario a completar onboarding. */
75 async redirectIfPerfilIncompleto() {
76 if (!this.isAuthenticated()) return false;
77 try {
78 const res = await API.request('/auth/perfil-estado');
79 if (!res?.completado) {
80 window.location.href = this.resolvePath('onboarding.html');
81 return true;
82 }
83 } catch (e) {
84 // Sin perfil consultable (p. ej. usuario demo) se permite navegar.
85 }
86 return false;
87 },
88
89 resolvePath(relativePath) {
90 const inPages = window.location.pathname.includes('/pages/');
91 if (inPages && !relativePath.startsWith('../') && !relativePath.startsWith('pages/')) {
92 return '../' + relativePath;
93 }
94 if (!inPages && relativePath.startsWith('pages/')) {
95 return relativePath;
96 }
97 return relativePath;
98 }
99 };