mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 00:56:34 +00:00
96 lines
2.3 KiB
TypeScript
96 lines
2.3 KiB
TypeScript
import { useCallback } from "react";
|
|
import { api, publicApi } from "../api/apiClient";
|
|
import { endpoints } from "../config/endpoints";
|
|
import type { UserProfile } from "../store/useAuthStore";
|
|
import { useAuthStore } from "../store/useAuthStore";
|
|
import { useKeyStore } from "../store/useKeyStore";
|
|
import { CryptoUtils } from "../utils/crypto";
|
|
import {
|
|
clearMasterKey,
|
|
loadMasterKey,
|
|
saveMasterKey,
|
|
} from "../utils/keystore";
|
|
|
|
export const useAuth = () => {
|
|
const { accessToken, user, isInitializing, setAuth, clearAuth } =
|
|
useAuthStore();
|
|
const { setMasterKey } = useKeyStore();
|
|
|
|
const isAuthenticated = !!accessToken;
|
|
|
|
// called after successful login — save master key
|
|
const setAuthStore = async (
|
|
access: string,
|
|
profile: UserProfile,
|
|
masterKey: CryptoKey,
|
|
) => {
|
|
await saveMasterKey(masterKey);
|
|
setMasterKey(masterKey);
|
|
setAuth(access, profile);
|
|
};
|
|
|
|
const logout = async () => {
|
|
try {
|
|
await api.post(endpoints.LOGOUT);
|
|
} catch (_error) {
|
|
} finally {
|
|
clearAuth();
|
|
setMasterKey(null);
|
|
await clearMasterKey();
|
|
}
|
|
};
|
|
|
|
const initialize = useCallback(async () => {
|
|
const { accessToken, user, setAuth, setInitializing } =
|
|
useAuthStore.getState();
|
|
|
|
// Restore master key from IndexedDB
|
|
try {
|
|
const masterKey = await loadMasterKey();
|
|
if (masterKey) setMasterKey(masterKey);
|
|
} catch {}
|
|
|
|
// If session in memory, don't trigger refresh/me again
|
|
if (accessToken && user) {
|
|
setInitializing(false);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// try session refresh
|
|
const { data: refreshData } = await publicApi.post(endpoints.REFRESH);
|
|
const { data: userData } = await api.get(endpoints.ME, {
|
|
headers: { Authorization: `Bearer ${refreshData.access}` },
|
|
});
|
|
setAuth(refreshData.access, userData);
|
|
} catch {
|
|
// grace for temporary network errors
|
|
} finally {
|
|
setInitializing(false);
|
|
}
|
|
}, [setMasterKey]);
|
|
|
|
const unlock = async (password: string) => {
|
|
if (!user) return;
|
|
|
|
try {
|
|
const { masterKey } = await CryptoUtils.deriveKeyBundle(
|
|
password,
|
|
user.email,
|
|
);
|
|
await saveMasterKey(masterKey);
|
|
setMasterKey(masterKey);
|
|
} catch {}
|
|
};
|
|
|
|
return {
|
|
isAuthenticated,
|
|
user,
|
|
isInitializing,
|
|
setAuthStore,
|
|
logout,
|
|
initialize,
|
|
unlock,
|
|
};
|
|
};
|