Files
geo/apps/admin-web/src/stores/auth.ts
T

88 lines
2.2 KiB
TypeScript
Raw Normal View History

import { defineStore } from "pinia";
import { computed, ref } from "vue";
import type { LoginRequest, UserInfo } from "@geo/shared-types";
import { authApi } from "@/lib/api";
import {
clearStoredSession,
readStoredSession,
setStoredTokens,
setStoredUser,
subscribeStoredSession,
type SessionSnapshot,
} from "@/lib/session";
export const useAuthStore = defineStore("auth", () => {
const accessToken = ref<string | null>(null);
const refreshToken = ref<string | null>(null);
const user = ref<UserInfo | null>(null);
const initialized = ref(false);
let unsubscribe: (() => void) | null = null;
function sync(snapshot: SessionSnapshot = readStoredSession()): void {
accessToken.value = snapshot.accessToken;
refreshToken.value = snapshot.refreshToken;
user.value = snapshot.user;
}
async function bootstrap(): Promise<void> {
if (!unsubscribe) {
unsubscribe = subscribeStoredSession(sync);
}
sync();
if (accessToken.value) {
try {
const currentUser = await authApi.me();
setStoredUser(currentUser);
} catch {
clearStoredSession();
}
}
initialized.value = true;
}
async function login(payload: LoginRequest): Promise<UserInfo> {
const response = await authApi.login(payload);
setStoredTokens({
accessToken: response.access_token,
refreshToken: response.refresh_token,
});
setStoredUser(response.user);
return response.user;
}
async function logout(): Promise<void> {
try {
if (accessToken.value) {
await authApi.logout();
}
} finally {
clearStoredSession();
}
}
const isAuthenticated = computed(() => Boolean(accessToken.value && user.value));
const membership = computed(() => user.value?.membership ?? null);
const isMembershipBlocked = computed(() => Boolean(membership.value?.blocked));
const kolProfile = computed(() => user.value?.kol_profile ?? null);
const isActiveKol = computed(() => kolProfile.value?.status === "active");
return {
accessToken,
refreshToken,
user,
initialized,
isAuthenticated,
membership,
isMembershipBlocked,
kolProfile,
isActiveKol,
bootstrap,
login,
logout,
};
});