diff --git a/src/app/coffee-abonnements/hooks/useSubscribeGuard.ts b/src/app/coffee-abonnements/hooks/useSubscribeGuard.ts new file mode 100644 index 0000000..a91db67 --- /dev/null +++ b/src/app/coffee-abonnements/hooks/useSubscribeGuard.ts @@ -0,0 +1,107 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import useAuthStore from '../../store/authStore'; + +type GuardState = 'checking' | 'allowed' | 'redirecting'; + +function hasPermission(permsSrc: any, permission: string) { + if (Array.isArray(permsSrc)) { + return ( + permsSrc.includes?.(permission) || + permsSrc.some?.((perm: any) => perm?.name === permission || perm?.key === permission) + ); + } + + if (permsSrc && typeof permsSrc === 'object') { + return !!permsSrc[permission]; + } + + return false; +} + +export function useSubscribeGuard() { + const router = useRouter(); + const user = useAuthStore((state) => state.user); + const isAuthReady = useAuthStore((state) => state.isAuthReady); + const accessToken = useAuthStore((state) => state.accessToken); + const refreshAuthToken = useAuthStore((state) => state.refreshAuthToken); + const [guardState, setGuardState] = useState('checking'); + + useEffect(() => { + let cancelled = false; + + const run = async () => { + if (!isAuthReady) { + if (!cancelled) setGuardState('checking'); + return; + } + + if (!user) { + if (!cancelled) setGuardState('redirecting'); + router.replace('/login'); + return; + } + + const uid = (user as any)?.id ?? (user as any)?._id ?? (user as any)?.userId; + if (!uid) { + if (!cancelled) setGuardState('redirecting'); + router.replace('/'); + return; + } + + let tokenToUse = accessToken; + try { + if (!tokenToUse && refreshAuthToken) { + const ok = await refreshAuthToken(); + if (ok) tokenToUse = useAuthStore.getState().accessToken; + } + } catch (error) { + console.error('useSubscribeGuard.refreshAuthToken', error); + } + + const base = process.env.NEXT_PUBLIC_API_BASE_URL || ''; + const url = `${base}/api/users/${uid}/permissions`; + + try { + const res = await fetch(url, { + method: 'GET', + cache: 'no-store', + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + ...(tokenToUse ? { Authorization: `Bearer ${tokenToUse}` } : {}), + }, + }); + + const body = await res.json().catch(() => null); + const permsSrc = body?.data?.permissions ?? body?.permissions ?? body; + const allowed = hasPermission(permsSrc, 'can_subscribe'); + + if (!allowed) { + if (!cancelled) setGuardState('redirecting'); + router.replace('/'); + return; + } + + if (!cancelled) setGuardState('allowed'); + } catch (error) { + console.error('useSubscribeGuard.permissions', error); + if (!cancelled) setGuardState('redirecting'); + router.replace('/'); + } + }; + + run(); + return () => { + cancelled = true; + }; + }, [isAuthReady, user, accessToken, refreshAuthToken, router]); + + return { + isChecking: guardState === 'checking', + isAllowed: guardState === 'allowed', + isRedirecting: guardState === 'redirecting', + }; +} \ No newline at end of file