fix: name a delegate from the accounts they share with you when the directory won't

This commit is contained in:
Linus Rath
2026-10-28 05:38:44 +01:00
parent 1a92eba702
commit 0bd63fca08
2 changed files with 23 additions and 3 deletions
@@ -27,9 +27,10 @@ function targets(withCarol = false): ShareTarget[] {
const ok = (changes: ShareChange[]): ShareChangeResult[] => changes.map((change) => ({ change, ok: true }));
function makeClient(options: { withCarol?: boolean; directory?: PrincipalListing; apply?: (c: ShareChange[]) => ShareChangeResult[] } = {}) {
function makeClient(options: { withCarol?: boolean; directory?: PrincipalListing; apply?: (c: ShareChange[]) => ShareChangeResult[]; sharedAccounts?: Array<{ id: string; name: string }> } = {}) {
return {
getAccountId: () => 'ci',
getSharedAccounts: () => options.sharedAccounts ?? [],
supportsPrincipals: () => true,
getPrincipals: vi.fn(async () => (options.directory ?? DIRECTORY_OFF).principals),
listPrincipals: vi.fn(async () => options.directory ?? DIRECTORY_OFF),
@@ -89,6 +90,17 @@ describe('DelegatesSettings', () => {
expect(screen.getAllByTestId('delegate-row')).toHaveLength(1);
});
it('names someone the directory does not list from the accounts they share with the user', async () => {
renderWith(makeClient({
withCarol: true,
directory: { principals: [ALICE], status: 'restricted', directoryQueriesOff: true },
sharedAccounts: [{ id: 'ck', name: 'org-carol@example.org' }],
}));
const row = await screen.findByTestId('delegate-row');
expect(within(row).getByText('org-carol@example.org')).toBeInTheDocument();
expect(within(row).queryByText('unknown_person')).toBeNull();
});
it('removes a person from every item, files included', async () => {
const client = makeClient({ withCarol: true });
renderWith(client);
@@ -75,8 +75,16 @@ export function DelegatesSettings() {
const ownIds = useMemo(() => (client ? [client.getAccountId()] : []), [client]);
const summaries = useMemo(() => (targets ? summarizeDelegates(targets, ownIds) : []), [targets, ownIds]);
const principalFor = useCallback((id: string): Principal | null =>
directory?.principals.find((p) => p.id === id) ?? remembered.get(id) ?? null, [directory, remembered]);
// Stalwart names a principal by its account id, and an account shared with
// the user is in the session under the owner's address: a last way to name
// someone the directory won't (Stalwart 1.0 with directory queries off).
const sessionAccounts = useMemo(() => new Map((client?.getSharedAccounts() ?? []).map((a) => [a.id, a.name])), [client]);
const principalFor = useCallback((id: string): Principal | null => {
const known = directory?.principals.find((p) => p.id === id) ?? remembered.get(id);
if (known) return known;
const accountName = sessionAccounts.get(id);
return accountName ? { id, name: accountName, email: accountName.includes('@') ? accountName : null, type: 'individual' } : null;
}, [directory, remembered, sessionAccounts]);
if (delegation.hidden || !client) return null;