Laravel-based OAuth/IAM service with Passport, Vue 3 frontend, and Docker Compose setup for local and production deployment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
92 lines
2.5 KiB
TypeScript
92 lines
2.5 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<string | null> {
|
|
const { data } = await axios.post<{ user: User; intended: string | null }>('/web-api/login', payload);
|
|
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;
|
|
},
|
|
},
|
|
});
|