| 1 | /** |
| 2 | * Deleting accounts, as a person's page and the Deleted accounts page show |
| 3 | * it: what went with an account, what stands in the way of deleting one, |
| 4 | * and what staff type to confirm. Identity checks all of it again. No |
| 5 | * Workers imports, so it can be tested under Node. |
| 6 | */ |
| 7 | import type { AccountDeletion, AccountWent } from "@g1t/contracts"; |
| 8 | |
| 9 | const plural = (n: number, one: string, many: string) => `${n} ${n === 1 ? one : many}`; |
| 10 | |
| 11 | /** What went with an account, in a line: "2 workspaces, 1 team, 3 repositories, 4 tokens, 1 SSH key". */ |
| 12 | export function accountWentSummary(went: AccountWent): string { |
| 13 | return [ |
| 14 | plural(went.workspaces, "workspace", "workspaces"), |
| 15 | plural(went.teams, "team", "teams"), |
| 16 | plural(went.repositories, "repository", "repositories"), |
| 17 | plural(went.tokens, "token", "tokens"), |
| 18 | plural(went.sshKeys, "SSH key", "SSH keys"), |
| 19 | ].join(", "); |
| 20 | } |
| 21 | |
| 22 | /** Why staff cannot delete the account, in a sentence about it, or null. */ |
| 23 | export function staffDeletionRefusal(deletion: AccountDeletion): string | null { |
| 24 | if (deletion.protected) return `${deletion.username} is protected and can never be deleted.`; |
| 25 | const slugs = deletion.sole_owner_of.map((workspace) => workspace.slug); |
| 26 | if (slugs.length === 0) return null; |
| 27 | return `${deletion.username} is the only owner of ${slugs.length === 1 ? "1 workspace" : `${slugs.length} workspaces`}. Each needs another owner, or to be deleted by its owner, first.`; |
| 28 | } |
| 29 | |
| 30 | /** Whether what staff typed is the username. Identity checks it again. */ |
| 31 | export function confirmsUsername(username: string, typed: string): boolean { |
| 32 | const value = typed.trim(); |
| 33 | return value !== "" && value.toLowerCase() === username.toLowerCase(); |
| 34 | } |