g1t/apps/web/app/lib/account-settings.ts

78 lines2,894 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1/**
2 * Your own settings: one page for each part, at `/settings/<page>`, so the
3 * docs, emails and messages can link to exactly the one they mean.
4 */
5
6export type AccountSettingsPage =
7 | "profile"
8 | "emails"
9 | "invites"
10 | "keys"
11 | "tokens"
12 | "github"
13 | "applications"
14 | "security-log";
15
16/** Each page's name and what it is for, in the sidebar's order. */
17export const ACCOUNT_SETTINGS: Record<AccountSettingsPage, { title: string; about: string }> = {
18 profile: { title: "Profile", about: "Your picture, and what everyone sees on your profile." },
19 emails: {
20 title: "Emails",
21 about:
22 "Your primary address gets account mail and password resets. Any confirmed address signs you in and can reset your password, and commits that carry it are shown as yours.",
23 },
24 invites: { title: "Invites", about: "Bring people to g1t, and see which invites were used." },
25 keys: { title: "SSH keys", about: "Keys that let git on your computers reach g1t as you." },
26 tokens: {
27 title: "Access tokens",
28 about:
29 "Use a token as the password when git asks for one over HTTPS, and to authenticate agents and the API. A token here acts as you.",
30 },
31 github: {
32 title: "GitHub",
33 about: "Sign in with your GitHub account, and import or mirror repositories you can reach there.",
34 },
35 applications: {
36 title: "Connected applications",
37 about:
38 "Applications you signed in to through your browser, such as an agent connected to the g1t MCP server. Signing one out ends its access at once.",
39 },
40 "security-log": {
41 title: "Security log",
42 about:
43 "Changes to your addresses and password, by you or by g1t staff. If you do not recognise one, reset your password.",
44 },
45};
46
47/** Where the first page is: `/settings` goes there. */
48export const FIRST_SETTINGS_PAGE = "/settings/profile";
49
50/**
51 * The sections of the old single settings page, by their `#anchor`, and
52 * the page each now has. Links like `g1t.sh/settings#emails` in old email
53 * and bookmarks still land in the right place.
54 */
55const OLD_ANCHORS: Record<string, AccountSettingsPage> = {
56 picture: "profile",
57 profile: "profile",
58 emails: "emails",
59 github: "github",
60 invites: "invites",
61 "ssh-keys": "keys",
62 tokens: "tokens",
63 applications: "applications",
64 "security-log": "security-log",
65};
66
67/** The page an old `#anchor` of the settings page now lives at, if it was one. */
68export function settingsPathForHash(hash: string): string | null {
69 const page = OLD_ANCHORS[hash.replace(/^#/, "")];
70 return page ? `/settings/${page}` : null;
71}
72
73/** Which settings page a path is, or null when it is none. */
74export function accountSettingsPage(pathname: string): AccountSettingsPage | null {
75 const match = /^\/settings\/([^/]+)\/?$/.exec(pathname);
76 const page = match?.[1];
77 return page && page in ACCOUNT_SETTINGS ? (page as AccountSettingsPage) : null;
78}