import { defineStore } from "pinia"; import { ref } from "vue"; import { getLoginKey, login as apiLogin, devLogin, fetchMe } from "../api/auth"; import { setToken, clearToken, getToken } from "../utils/auth"; import { encryptLoginPayload } from "../utils/loginCrypto"; import type { UserInfo } from "../types/api"; import { useStudyStore } from "./study"; import { useSessionStore } from "./session"; export const useAuthStore = defineStore("auth", () => { const LAST_LOGIN_EMAIL_KEY = "ctms_last_login_email"; const allowInsecureDevLogin = import.meta.env.VITE_RUNTIME_ENV === "development" && import.meta.env.VITE_ALLOW_INSECURE_DEV_LOGIN === "true"; const token = ref(getToken()); const user = ref(null); const loading = ref(false); const forceLogin = ref(false); const login = async (email: string, password: string) => { loading.value = true; try { const { data } = allowInsecureDevLogin && !window.isSecureContext ? await devLogin({ email, password }) : await encryptedLogin(email, password); token.value = data.access_token; await setToken(data.access_token); useSessionStore().resetActivity(); localStorage.setItem(LAST_LOGIN_EMAIL_KEY, email); const me = await fetchMeAction(); const studyStore = useStudyStore(); const userKey = me?.email || email; await studyStore.restoreStudyForUser(userKey, { preferActive: me?.is_admin }); await studyStore.loadCurrentStudyPermissions().catch(() => {}); forceLogin.value = false; } finally { loading.value = false; } }; const encryptedLogin = async (email: string, password: string) => { const { data: loginKey } = await getLoginKey(); const ciphertext = await encryptLoginPayload(loginKey.public_key, { email, password, challenge: loginKey.challenge, }); return apiLogin({ key_id: loginKey.key_id, challenge: loginKey.challenge, ciphertext, }); }; const fetchMeAction = async () => { const { data } = await fetchMe(); user.value = data; if (data?.email) { localStorage.setItem(LAST_LOGIN_EMAIL_KEY, data.email); } return data; }; const logout = async () => { const studyStore = useStudyStore(); const sessionStore = useSessionStore(); const userKey = user.value?.email || localStorage.getItem(LAST_LOGIN_EMAIL_KEY) || ""; studyStore.rememberCurrentStudyForUser(userKey); token.value = null; user.value = null; forceLogin.value = false; sessionStore.resetActivity(); await clearToken(); studyStore.clearCurrentStudy(); }; return { token, user, loading, forceLogin, login, fetchMe: fetchMeAction, logout, setToken: (newToken: string) => { token.value = newToken; }, requestReLogin: () => { forceLogin.value = true; }, }; });