Files
WebDrop/web/src/core-bridge/worker/accountChannels.ts
T

34 lines
2.4 KiB
TypeScript

import { ChannelSession } from '@webdrop/core';
import { getResource, importResources, listResourceDeletes, type SavedResource } from '../database';
import { openChannelGrant } from './channelGrant';
import { makeLink } from './links';
import { apiFetch, readJson } from './http';
import type { InvitationKeyPair } from './accountCrypto';
import type { ChannelWire } from './wire';
import type { AccountChannelBody } from '../generated/api';
import { channelCache } from './resourceMetadata';
export async function recoverAccountChannels(username: string, keys: InvitationKeyPair, signal: AbortSignal): Promise<void> {
const grants = await apiFetch('/accounts/channels', { signal }).then((r) => r.json() as Promise<AccountChannelBody[]>);
const deletes = new Map((await listResourceDeletes()).map((row) => [row.id, row.modifiedAt]));
for (const grant of grants) {
if (grant.role !== 'owner' && grant.role !== 'member') throw new Error('空间成员权限无效');
if (signal.aborted) throw new DOMException('账号已切换', 'AbortError');
if ((deletes.get(grant.channel_id) ?? -1) >= grant.created_at || await getResource(grant.channel_id)) continue;
const parsed = await openChannelGrant(grant.payload, username, grant.channel_id, keys.privateKey, grant.role, self.location.origin);
const session = await ChannelSession.open(makeLink(self.location.origin, parsed.id, parsed.keys));
try {
const info = await readJson<ChannelWire>(`/channels/${session.id}`, session.authHeaders('read'));
session.verifyChannelInfo(info);
if (grant.role === 'owner' && info.creator_account !== username) throw new Error('空间所属账号不匹配');
const resource: SavedResource = { ...channelCache(info), id: session.id, kind: 'channel', mode: session.mode, role: grant.role,
creatorAccount: info.creator_account ?? undefined, name: info.settings.name ?? undefined,
link: session.link(self.location.origin), ...(grant.role === 'owner' ? { ownerLink: session.link(self.location.origin, 'owner') } : {}),
endpointSecret: new Uint8Array(32), createdAt: info.created_at, modifiedAt: grant.created_at, expiresAt: info.expires_at,
seats: info.settings.seats, maxDownloads: info.settings.file_max_downloads };
if (signal.aborted) throw new DOMException('账号已切换', 'AbortError');
await importResources([resource]);
} finally { session.dispose(); }
}
}