'use client'; import { useCallback, useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { Ban, CheckCircle2, ChevronRight, FileKey2, Loader2 } from 'lucide-react'; import { useAuth } from '@/components/id/auth-provider'; import { IdShell } from '@/components/id/shell'; import { usePublicSettings } from '@/components/id/public-settings-provider'; import { useToast } from '@/components/id/toast-provider'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { useRequireAuth } from '@/hooks/use-require-auth'; import { fetchUserOAuthConsents, getApiErrorMessage, revokeOAuthConsent, type OAuthUserConsent } from '@/lib/api'; function formatGrantedAt(value: string) { return new Intl.DateTimeFormat('ru-RU', { day: 'numeric', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(new Date(value)); } export default function DataConsentsPage() { const router = useRouter(); const { user, token } = useAuth(); const { projectName } = usePublicSettings(); const { isReady, isPinLocked } = useRequireAuth(); const { showToast } = useToast(); const [consents, setConsents] = useState([]); const [loading, setLoading] = useState(true); const [selectedConsent, setSelectedConsent] = useState(null); const [revoking, setRevoking] = useState(false); const loadConsents = useCallback(async () => { if (!user || !token || isPinLocked) return; setLoading(true); try { const response = await fetchUserOAuthConsents(user.id, token); setConsents(response.consents ?? []); } catch (error) { showToast(getApiErrorMessage(error, 'Не удалось загрузить доступы') ?? 'Ошибка'); } finally { setLoading(false); } }, [isPinLocked, showToast, token, user]); useEffect(() => { if (isReady && user && !isPinLocked) void loadConsents(); }, [isPinLocked, isReady, loadConsents, user]); async function handleRevoke() { if (!user || !token || !selectedConsent) return; setRevoking(true); try { await revokeOAuthConsent(user.id, selectedConsent.id, token); setConsents((current) => current.filter((item) => item.id !== selectedConsent.id)); setSelectedConsent(null); showToast('Доступ отозван'); } catch (error) { showToast(getApiErrorMessage(error, 'Не удалось отозвать доступ') ?? 'Ошибка'); } finally { setRevoking(false); } } return (

Доступы к данным

Настройте, к каким данным аккаунта есть доступ у сервисов. После отзыва при следующем входе доступ нужно будет подтвердить снова.

{loading ? (
Загружаем приложения...
) : consents.length === 0 ? (

Вы ещё не выдавали доступ ни одному приложению

) : ( consents.map((consent) => ( )) )}
!open && setSelectedConsent(null)}> {selectedConsent ? ( <>
{selectedConsent.clientName}

Выданы {formatGrantedAt(selectedConsent.grantedAt)}

API {projectName}

    {selectedConsent.scopes.map((scope) => (
  • {scope.description ?? scope.name}
  • ))}

ID: {selectedConsent.id.slice(0, 8).toUpperCase()}

) : null}
); }