import { useCallback, useEffect, useMemo, useState } from 'react'; import { PartRight, RESTConfig, UserMe, UserResource } from '@/back-api'; import { environment, getApiUrl } from '@/environment'; import { useServiceContext } from '@/service/ServiceContext'; import { SessionState } from '@/service/SessionState'; import { isBrowser } from '@/utils/layout'; import { parseToken } from '@/utils/sso'; import { createListCollection } from '@chakra-ui/react'; const TOKEN_KEY = 'karusic-token-key-storage'; export const USERS_COLLECTION = createListCollection({ items: [ { label: "admin", value: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E" }, { label: "NO_USER", value: "svelte" }, ], }) export const USERS = { admin: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E', NO_USER: '', } as const; export const getUserToken = () => { return localStorage.getItem(TOKEN_KEY); }; export type RightPart = 'admin' | 'user'; export function getRestConfig(): RESTConfig { return { server: getApiUrl(), token: getUserToken() ?? '', }; } export type SessionServiceProps = { token?: string; setToken: (token: string) => void; clearToken: () => void; login?: string; hasReadRight: (part: RightPart) => boolean; hasWriteRight: (part: RightPart) => boolean; state: SessionState; getRestConfig: () => RESTConfig; }; export const useSessionService = (): SessionServiceProps => { const { session } = useServiceContext(); return session; }; export const useSessionServiceWrapped = (): SessionServiceProps => { const [token, setToken] = useState( isBrowser ? (localStorage.getItem(TOKEN_KEY) ?? undefined) : undefined ); const [state, setState] = useState(SessionState.NO_USER); const [config, setConfig] = useState(undefined); const updateRight = useCallback(() => { if (isBrowser) { console.log('Detect a new token...'); setState(SessionState.NO_USER); setConfig(undefined); if (token === undefined) { console.log(` ==> No User`); setState(SessionState.NO_USER); localStorage.removeItem(TOKEN_KEY); } else if (token === '__LOGOUT__') { console.log(` ==> disconnection: ${token}`); setState(SessionState.DISCONNECT); localStorage.removeItem(TOKEN_KEY); } else if (!['__LOGOUT__', '__FAIL__', '__CANCEL__'].includes(token)) { console.log(' ==> Login ... (try to keep right)'); setState(SessionState.CONNECTING); localStorage.setItem(TOKEN_KEY, token); UserResource.getMe({ restConfig: getRestConfig(), }) .then((response: UserMe) => { //console.log(` ==> New right arrived to '${response.login}'`); setState(SessionState.CONNECTED); setConfig(response); }) .catch((error) => { setState(SessionState.CONNECTION_FAIL); //console.log(` ==> Fail to get right: '${error}'`); localStorage.removeItem(TOKEN_KEY); }); } } }, [localStorage, parseToken, token]); const setTokenLocal = useCallback( (token: string) => { setToken(token); updateRight(); }, [updateRight, setToken] ); const clearToken = useCallback(() => { setToken(undefined); updateRight(); }, [updateRight, setToken]); const hasReadRight = useCallback( (part: RightPart) => { //console.log(`config = ${JSON.stringify(config, null, 2)}`); const right = config?.rights[environment.applName]; if (right === undefined) { return false; } return [PartRight.READ, PartRight.READ_WRITE].includes(right[part]); }, [config] ); const hasWriteRight = useCallback( (part: RightPart) => { const right = config?.rights[environment.applName]; if (right === undefined) { return false; } return [PartRight.READ, PartRight.READ_WRITE].includes(right[part]); }, [config] ); const getRestConfig = useCallback((): RESTConfig => { return { server: getApiUrl(), token: token ?? '', }; }, [token]); useEffect(() => { updateRight(); }, [updateRight]); return { token, setToken: setTokenLocal, clearToken, login: config?.login, hasReadRight, hasWriteRight, state, getRestConfig, }; }; export const useHasRight = (part: RightPart) => { const { token, hasReadRight, hasWriteRight } = useSessionService(); const isReadable = useMemo(() => { console.log(`get is read for: ${part} ==> ${hasReadRight(part)}`); return hasReadRight(part); }, [token, hasReadRight, part]); const isWritable = useMemo(() => { return hasWriteRight(part); }, [token, hasWriteRight, part]); return { isReadable, isWritable }; };