mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 16:13:15 +00:00
32 lines
1.7 KiB
TypeScript
32 lines
1.7 KiB
TypeScript
import type { IJMAPClient } from '@/lib/jmap/client-interface';
|
|
import type { PolicySubject } from './policy-scopes';
|
|
|
|
type SubjectClient = Pick<IJMAPClient, 'getUsername' | 'getSharedAccounts' | 'getAccountInfo' | 'getPrincipalTypes'>;
|
|
|
|
/**
|
|
* Who a signed-in client is for the domain and group scopes: its login
|
|
* address and the addresses of the group accounts in its session. Stalwart
|
|
* names group accounts by their address (local-data/org-features-facts.md
|
|
* §1). A mailbox another user shared is also a non-personal account, so the
|
|
* principal type decides; when the server won't say, every non-personal
|
|
* account counts, which only matters if an admin put a person's address in a
|
|
* group scope.
|
|
*/
|
|
export async function policySubjectForClient(client: SubjectClient | null): Promise<PolicySubject | null> {
|
|
if (!client || typeof client.getUsername !== 'function') return null;
|
|
const email = client.getUsername()?.trim().toLowerCase() ?? '';
|
|
if (!email) return null;
|
|
// A client without a session yet (or a stand-in) has no shared accounts.
|
|
const shared = (typeof client.getSharedAccounts === 'function' ? client.getSharedAccounts() : [])
|
|
.filter((account) => !account.isPrimary && client.getAccountInfo?.(account.id)?.isPersonal === false)
|
|
.filter((account) => account.name.includes('@'));
|
|
const types = shared.length > 0 && typeof client.getPrincipalTypes === 'function'
|
|
? await client.getPrincipalTypes(shared.map((account) => account.id)).catch(() => null)
|
|
: null;
|
|
const groups = shared
|
|
.filter((account) => !types || types[account.id] === 'group')
|
|
.map((account) => account.name.trim().toLowerCase())
|
|
.sort();
|
|
return { email, groups };
|
|
}
|