Files
oauth/resources/js/stores/auth.ts
2026-07-27 17:20:02 +02:00

105 lines
3.0 KiB
TypeScript

import { defineStore } from 'pinia';
import axios from 'axios';
import type { User } from '../types/models';
interface AuthState {
user: User | null;
checked: boolean;
}
interface Credentials {
email: string;
password: string;
remember?: boolean;
}
interface RegisterPayload {
name: string;
email: string;
password: string;
password_confirmation: string;
}
interface RegisterResult {
bootstrap: boolean;
message?: string;
}
export const useAuthStore = defineStore('auth', {
state: (): AuthState => ({
user: null,
checked: false,
}),
getters: {
isAuthenticated: (state): boolean => state.user !== null,
isAdmin: (state): boolean => Boolean(state.user?.roles?.includes('admin')),
},
actions: {
async fetchUser(): Promise<void> {
try {
const { data } = await axios.get<{ user: User }>('/web-api/me');
this.user = data.user;
} catch {
this.user = null;
} finally {
this.checked = true;
}
},
async login(payload: Credentials): Promise<{ twoFactor: true } | { twoFactor: false; intended: string | null }> {
const { data } = await axios.post<{ two_factor?: true; user?: User; intended?: string | null }>('/web-api/login', payload);
if (data.two_factor) {
return { twoFactor: true };
}
this.user = data.user!;
this.checked = true;
return { twoFactor: false, intended: data.intended ?? null };
},
async loginTwoFactor(code: string): Promise<string | null> {
const { data } = await axios.post<{ user: User; intended: string | null }>('/web-api/login/2fa', { code });
this.user = data.user;
this.checked = true;
return data.intended ?? null;
},
// Si todavía no hay ningún usuario en el sistema, el registro loguea de
// una como admin (bootstrap). Si ya hay usuarios, la cuenta queda
// pendiente hasta que un admin la aprueba (ver AuthController::register).
async register(payload: RegisterPayload): Promise<RegisterResult> {
const { data } = await axios.post<{
bootstrap?: true;
user?: User;
pending?: true;
message?: string;
}>('/web-api/register', payload);
if (data.bootstrap && data.user) {
this.user = data.user;
this.checked = true;
return { bootstrap: true };
}
return { bootstrap: false, message: data.message };
},
async setupIsEmpty(): Promise<boolean> {
const { data } = await axios.get<{ empty: boolean }>('/web-api/setup-status');
return data.empty;
},
async logout(): Promise<void> {
await axios.post('/web-api/logout');
this.user = null;
},
},
});