feat!: drop the backend-side elevation windows; password and passkey sessions share capabilities, passkeys guard what nodes verify; the trust page lists added and removed passkeys [CI]
This commit is contained in:
1 parent
f704c66dd9
commit
4106f831dc
34 files changed
+191
-1364
No files matched your search
@@ -36,29 +36,7 @@ export function withQuery(path: string, query?: Query): string {
|
||||
return text ? `${path}?${text}` : path
|
||||
}
|
||||
|
||||
/**
|
||||
* 敏感操作(加节点、吊销、改凭证)需要先触碰 passkey 开一个提权窗口:后端返回 403 `elevation_required`(detail 是窗口种类)时,
|
||||
* 调用已注册的处理函数(弹出 passkey 触碰),成功后把原请求重试一次。
|
||||
*/
|
||||
let elevationHandler: ((elevation: string) => Promise<boolean>) | null = null
|
||||
|
||||
export function setElevationHandler(handler: ((elevation: string) => Promise<boolean>) | null) {
|
||||
elevationHandler = handler
|
||||
}
|
||||
|
||||
async function request<T>(method: string, path: string, body?: unknown, init?: RequestInit): Promise<T> {
|
||||
try {
|
||||
return await send<T>(method, path, body, init)
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && e.code === 'elevation_required' && elevationHandler) {
|
||||
if (await elevationHandler(e.detail)) return send<T>(method, path, body, init)
|
||||
throw new ApiError(403, e.code, '这个操作需要先用 Passkey 确认,已取消')
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
async function send<T>(method: string, path: string, body?: unknown, init?: RequestInit): Promise<T> {
|
||||
const headers: Record<string, string> = { Accept: 'application/json', ...authHeaders() }
|
||||
if (body !== undefined) headers['Content-Type'] = method === 'PATCH' ? 'application/merge-patch+json' : 'application/json'
|
||||
if (method !== 'GET' && csrfToken) headers['X-CSRF-Token'] = csrfToken
|
||||
|
||||
Reference in new issue
Block a user