import useLocalStorageState from 'use-local-storage-state' import { control as defaultControlLevel } from '@freesewing/config' /* * When there is no account, we use this making it easy to check for username * or control */ const noAccount = { username: false, control: defaultControlLevel } /* * FreeSewing's useAccount hook. Grants access to the (data in the) user's account */ export function useAccount() { /* * Account is stored in persisted state (saved to local storage) */ const [account, setAccount] = useLocalStorageState('fs-account', { defaultValue: noAccount }) /* * Admins are allowed to inpersonate a user. * When that happens, we store the admin's account in this admin field (saved in local storage). * When the admin ends the impersonation, we copy the account data under the admin key back into * the regular account key. * With this, admins would have to re-login after impersonating a user. */ const [admin, setAdmin] = useLocalStorageState('fs-admin', { defaultValue: noAccount }) /* * This holds the JSON Web Token (JWT) returned from the backend after authentication */ const [token, setToken] = useLocalStorageState('fs-token', { defaultValue: null }) /* * We use this to allow 'welcome back' style UI, asking for password, not username */ const [seenUser, setSeenUser] = useLocalStorageState('fs-seen-user', { defaultValue: false }) /* * Clear user data when signing out */ const signOut = () => { console.log('SIGN OUT') setAccount(noAccount) setToken(null) } /* * Impersonate a user. * Only admins can do this but that is enforced at the backend. */ const impersonate = (data) => { /* * Store token and account data in admin, so we can restore them later */ setAdmin({ token, account }) /* * Create new account object based on the data passed in */ const newAccount = { ...data.account, impersonatingAdmin: { id: account.id, username: account.username }, } /* * Now set the new account and token */ setAccount(newAccount) setToken(data.token) } /* * When impersonation ends, restore the original admin account */ const stopImpersonating = () => { setAccount(admin.account) setToken(admin.token) clearAdmin() } /* * Don't keep account data lingering in the admin key */ const clearAdmin = () => setAdmin(noAccount) /* * Return everything this hook provides */ return { account, setAccount, token, setToken, seenUser, setSeenUser, signOut, admin, clearAdmin, impersonate, stopImpersonating, control: account?.control || 2, } }