Skip to content
40 linesCodeBlameRaw
1/**
2 * What the Invite dialog and the Invitations page post, answered the same
3 * way from whichever page they are on (Members, Invitations): inviting
4 * someone, sending an invitation again, and revoking one. Identity checks
5 * the owner, the plan and the invite allowance again. Answering an
6 * invitation of your own is lib/invitations.server.ts.
7 */
8import type { User } from "@g1t/contracts";
9
10import type { InvitationResult, InviteResult } from "./invites";
11import { inviteTarget } from "./people-search";
12import { identity } from "./services.server";
13
14/**
15 * Invites whoever the form names (`member`: a username or an address) with
16 * `role` and an optional `message`. Nobody joins without saying yes: a
17 * username or an address gets an invitation to accept or decline.
18 */
19export async function inviteFromForm(user: User, slug: string, form: FormData): Promise<InviteResult> {
20 const member = String(form.get("member") ?? "").trim();
21 const who = inviteTarget(member);
22 if (!who) return { error: "Enter a g1t username or an email address.", outOfInvites: false };
23 const role = form.get("role") === "owner" ? "owner" : "member";
24 const message = String(form.get("message") ?? "").trim() || null;
25 const result = await identity.inviteMember(user, slug, { ...who, role, message });
26 if (!result.ok) return { error: result.error.message, outOfInvites: result.error.code === "limit" };
27 return { invited: "email" in who ? who.email : `@${who.username}`, outOfInvites: false };
28}
29
30/** `action=revoke-invite` or `action=resend-invite`, with the invitation's `id`; null for anything else. */
31export async function invitationFromForm(user: User, slug: string, form: FormData): Promise<InvitationResult | null> {
32 const action = form.get("action");
33 const id = String(form.get("id") ?? "").trim();
34 if (action !== "revoke-invite" && action !== "resend-invite") return null;
35 if (!id) return { error: "Which invitation?", id };
36 const result =
37 action === "revoke-invite" ? await identity.revokeWorkspaceInvite(user, slug, id) : await identity.resendWorkspaceInvite(user, slug, id);
38 if (!result.ok) return { error: result.error.message, id };
39 return { done: action === "revoke-invite" ? "revoked" : "resent", id };
40}