Files
live_recorder/frontend/src/stores/auth.ts
T

69 lines
1.7 KiB
TypeScript

import { computed, ref } from "vue";
import { defineStore } from "pinia";
import apiClient from "@/api/client";
import type { AuthenticatedUser, LoginResponse } from "@/types";
const USER_STORAGE_KEY = "live-recorder-user";
const TOKEN_STORAGE_KEY = "live-recorder-token";
export const useAuthStore = defineStore("auth", () => {
const token = ref(localStorage.getItem(TOKEN_STORAGE_KEY) ?? "");
const user = ref<AuthenticatedUser | null>(
(() => {
const raw = localStorage.getItem(USER_STORAGE_KEY);
return raw ? (JSON.parse(raw) as AuthenticatedUser) : null;
})()
);
const isAuthenticated = computed(() => Boolean(token.value));
function persistSession(session: LoginResponse) {
token.value = session.token;
user.value = session.user;
localStorage.setItem(TOKEN_STORAGE_KEY, session.token);
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(session.user));
}
function clearSession() {
token.value = "";
user.value = null;
localStorage.removeItem(TOKEN_STORAGE_KEY);
localStorage.removeItem(USER_STORAGE_KEY);
}
async function login(username: string, password: string) {
const { data } = await apiClient.post<LoginResponse>("/auth/login", {
username,
password
});
persistSession(data);
return data;
}
async function logout() {
try {
await apiClient.post("/auth/logout");
} finally {
clearSession();
}
}
async function changePassword(currentPassword: string, newPassword: string) {
await apiClient.post("/auth/change-password", {
currentPassword,
newPassword
});
}
return {
token,
user,
isAuthenticated,
login,
logout,
changePassword,
clearSession
};
});