Files
MoShiro/web/admin/src/pages/OwnerPicker.tsx
T

61 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react'
import { api } from '@shared/api/client'
import type { Page, PasskeyDto, TrustStateDto } from '@shared/api/types'
/**
* 选这个节点的属主(必选,至少一把):允许授权它 extension 会话(web ssh 等,以后)、解密它加密内容的 passkey。只是选,不需要触碰 Passkey:
* 选定的凭证 id 会写进安装命令,节点装上时固定在本地,之后面板改不了。默认是操作员集合里的全部。
* 还没有建立信任根时不显示选项,只提示去建立。
*/
export function OwnerPicker({ value, onChange }: { value: string[] | null; onChange: (next: string[]) => void }) {
const [trust, setTrust] = useState<TrustStateDto>()
const [own, setOwn] = useState<PasskeyDto[]>([])
useEffect(() => {
let alive = true
api
.get<TrustStateDto>('/api/admin/trust')
.then((t) => {
if (!alive) return
setTrust(t)
if (value === null) onChange(t.operators ?? [])
})
.catch(() => undefined)
api
.get<Page<PasskeyDto>>('/api/admin/auth/passkeys')
.then((list) => alive && setOwn(list.items))
.catch(() => undefined)
return () => {
alive = false
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
if (!trust) return null
if (!trust.initialized) {
return <div className="notice warn">还没有建立信任根:每个节点都必须有属主(passkey),先到「系统 → 信任」用 Passkey 建立信任根,才能添加节点。</div>
}
const chosen = new Set(value ?? [])
const name = (id: string) => own.find((p) => p.id === id)?.name ?? `其他账号的 Passkey(${id.slice(0, 8)}…)`
return (
<div className="stack" style={{ gap: 4 }}>
{(trust.operators ?? []).map((id) => (
<label key={id} className="switch">
<input
type="checkbox"
checked={chosen.has(id)}
onChange={(e) => {
const next = new Set(chosen)
if (e.target.checked) next.add(id)
else next.delete(id)
onChange([...next])
}}
/>
{name(id)}
</label>
))}
</div>
)
}