feat: authentication integration
This commit is contained in:
136
web/src/store/auth.ts
Normal file
136
web/src/store/auth.ts
Normal file
@ -0,0 +1,136 @@
|
||||
import {
|
||||
deleteAccount,
|
||||
getAllAccounts,
|
||||
updateAccountInfo,
|
||||
type LocalAccount,
|
||||
} from "@/repository/account";
|
||||
import type { UserProfile } from "@/types";
|
||||
import { create } from "zustand";
|
||||
import { useDbStore } from "./db";
|
||||
import { fetchProfileApi } from "@/api/profile";
|
||||
|
||||
export interface IAuthState {
|
||||
profile: UserProfile | null;
|
||||
authenticating: boolean;
|
||||
activeAccount: LocalAccount | null;
|
||||
loadingAccounts: boolean;
|
||||
accounts: LocalAccount[];
|
||||
signInRequired: boolean;
|
||||
|
||||
loadAccounts: () => Promise<void>;
|
||||
updateActiveAccount: (account: LocalAccount) => Promise<void>;
|
||||
authenticate: () => Promise<void>;
|
||||
requireSignIn: () => void;
|
||||
signOut: () => void;
|
||||
}
|
||||
|
||||
const getActiveAccountId = (): string | null => {
|
||||
const accountId = localStorage.getItem("guard-selected");
|
||||
return accountId;
|
||||
};
|
||||
|
||||
const saveActiveAccountId = (accountId: string): void => {
|
||||
localStorage.setItem("guard-selected", accountId);
|
||||
};
|
||||
|
||||
const resetActiveAccount = (): void => {
|
||||
localStorage.removeItem("guard-selected");
|
||||
};
|
||||
|
||||
// TODO: maybe add deleteActiveAccount
|
||||
|
||||
export const useAuth = create<IAuthState>((set, get) => ({
|
||||
profile: null,
|
||||
authenticating: false,
|
||||
activeAccount: null,
|
||||
accounts: [],
|
||||
loadingAccounts: false,
|
||||
signInRequired: false,
|
||||
|
||||
updateActiveAccount: async (account) => {
|
||||
set({ activeAccount: account });
|
||||
|
||||
saveActiveAccountId(account.accountId);
|
||||
|
||||
set({ signInRequired: false });
|
||||
},
|
||||
|
||||
loadAccounts: async () => {
|
||||
set({ loadingAccounts: true });
|
||||
|
||||
const db = useDbStore.getState().db;
|
||||
if (!db) return;
|
||||
|
||||
const accounts = await getAllAccounts(db);
|
||||
|
||||
console.log("loaded accounts:", accounts);
|
||||
|
||||
if (!accounts || accounts.length === 0) {
|
||||
set({ signInRequired: true });
|
||||
}
|
||||
|
||||
const active = getActiveAccountId();
|
||||
|
||||
if (!active) {
|
||||
set({ signInRequired: true });
|
||||
}
|
||||
|
||||
const account = accounts.find((acc) => acc.accountId === active);
|
||||
|
||||
if (!account) {
|
||||
resetActiveAccount();
|
||||
set({ signInRequired: true });
|
||||
}
|
||||
|
||||
set({ activeAccount: account, accounts, loadingAccounts: false });
|
||||
},
|
||||
|
||||
authenticate: async () => {
|
||||
const { authenticating } = get();
|
||||
if (authenticating) return;
|
||||
|
||||
set({ authenticating: true });
|
||||
|
||||
try {
|
||||
const response = await fetchProfileApi();
|
||||
console.log("authenticate response:", response);
|
||||
|
||||
try {
|
||||
// update local account information
|
||||
const db = useDbStore.getState().db;
|
||||
if (db) {
|
||||
await updateAccountInfo(db, {
|
||||
accountId: response.id,
|
||||
label: response.full_name,
|
||||
...(response.profile_picture
|
||||
? { profilePicture: response.profile_picture }
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
set({ profile: response });
|
||||
}
|
||||
} catch (err) {
|
||||
// TODO: set error
|
||||
console.log(err);
|
||||
} finally {
|
||||
set({ authenticating: false });
|
||||
}
|
||||
},
|
||||
|
||||
requireSignIn: () => set({ signInRequired: true }),
|
||||
|
||||
signOut: async () => {
|
||||
resetActiveAccount();
|
||||
|
||||
const db = useDbStore.getState().db;
|
||||
const activeAccount = get().activeAccount;
|
||||
if (db && activeAccount) {
|
||||
await deleteAccount(db, activeAccount.accountId);
|
||||
}
|
||||
|
||||
await get().loadAccounts();
|
||||
|
||||
set({ activeAccount: null, signInRequired: true });
|
||||
},
|
||||
}));
|
Reference in New Issue
Block a user