import { useEffect, useRef, useState, type FormEvent } from 'react'; import { ShieldCheck } from 'lucide-react'; import { NativeApi } from '@api/native'; import { Button } from '@components/ui/button'; import { Input } from '@components/ui/input'; import { Label } from '@components/ui/label'; import type { NativeAuthStatus } from '@typings/native'; interface Props { status: NativeAuthStatus | null; loading: boolean; onRetry: () => Promise; onLogin: (email: string, password: string, signal: AbortSignal) => Promise; onError: (message: string) => void; } export function NativeAccountAccess({ status, loading, onRetry, onLogin, onError }: Props) { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [recovering, setRecovering] = useState(false); const [pending, setPending] = useState(false); const [notice, setNotice] = useState(''); const request = useRef(); const embedded = window.self !== window.top; useEffect(() => () => request.current?.abort(), []); const submit = async (event: FormEvent) => { event.preventDefault(); if (embedded || request.current || !email.trim() || (!recovering && !password)) return; const controller = new AbortController(); request.current = controller; setPending(true); setNotice(''); onError(''); try { if (recovering) { // 匿名恢复同样先取预登录 CSRF,邮件提交不会绕过会话保护。 const next = await new NativeApi().authStatus(controller.signal); const api = new NativeApi(next.csrf_token); await api.ensureCsrf(controller.signal); await api.recover(email.trim(), controller.signal); if (!controller.signal.aborted) setNotice('如果此邮箱可以恢复登录,你会收到重置邮件。请在当前浏览器中打开邮件链接。'); } else await onLogin(email.trim(), password, controller.signal); } catch (error) { if (!controller.signal.aborted) onError(error instanceof Error ? error.message : '请求失败,请重试'); } finally { // 密码只在提交期间留在组件内存,任何结果都清空输入,不保存到浏览器存储。 setPassword(''); request.current = undefined; if (!controller.signal.aborted) setPending(false); } }; return

{loading ? '正在检查登录状态' : !status || !status.initialized || status.bootstrap.mode === 'locked' ? '安全初始化' : recovering ? '找回密码' : '管理员登录'}

{loading ?

正在连接认证服务…

: !status ?

暂时无法确认认证配置,请重试连接。

: !status.initialized || status.bootstrap.mode === 'locked' ?

{status.bootstrap.reason || '认证服务尚未配置,管理功能已锁定。'}

请由运营者配置 Supabase Auth,并在服务端明确授权管理员账号。此页面不提供公开注册或首次访问者创建管理员。

: <>

{recovering ? '输入管理员邮箱,我们会发送密码重置邮件。请使用此浏览器打开邮件中的链接。' : '使用已授权的 Supabase 管理员账号登录。会话通过 HttpOnly cookie 保存;前端不保存密码或管理员 token。'}

{embedded &&

嵌入页面无法可靠保存安全登录cookie,请先点击上方“在独立页面登录”,再登录或发送重置邮件。

}
setEmail(event.target.value)} required disabled={pending || embedded} className="mt-2" />
{!recovering &&
setPassword(event.target.value)} required disabled={pending || embedded} className="mt-2" />
}
{notice &&

{notice}

} }
; }