Initial working state: CL3.5 complete (Plesk sync + suspend/unsuspend)
This commit is contained in:
139
lib/agency.ts
Normal file
139
lib/agency.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import type { Database } from "@/lib/types";
|
||||
import { createSupabaseAdminClient } from "@/lib/supabase/admin";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/route";
|
||||
import { createSupabaseServerClient } from "@/lib/supabase/server";
|
||||
|
||||
export type AgencyContext = {
|
||||
userId: string;
|
||||
agencyId: string;
|
||||
role: "owner" | "admin" | "member";
|
||||
};
|
||||
|
||||
export function assertAgencyAdmin(context: AgencyContext) {
|
||||
if (context.role !== "owner" && context.role !== "admin") {
|
||||
throw new Error("Forbidden");
|
||||
}
|
||||
}
|
||||
|
||||
type AgencyMemberSummary = Pick<
|
||||
Database["public"]["Tables"]["agency_members"]["Row"],
|
||||
"agency_id" | "role"
|
||||
>;
|
||||
|
||||
async function getOrCreateAgencyMembership(
|
||||
userId: string,
|
||||
email?: string | null,
|
||||
) {
|
||||
const supabase = createSupabaseServerClient() as any;
|
||||
const admin = createSupabaseAdminClient() as any;
|
||||
|
||||
const { data: existingMembership } = (await supabase
|
||||
.from("agency_members")
|
||||
.select("agency_id, role")
|
||||
.eq("user_id", userId)
|
||||
.order("created_at", { ascending: true })
|
||||
.limit(1)
|
||||
.maybeSingle()) as { data: AgencyMemberSummary | null };
|
||||
|
||||
if (existingMembership) {
|
||||
return existingMembership;
|
||||
}
|
||||
|
||||
const defaultAgencyName = email
|
||||
? `${email.split("@")[0] ?? "New"} Agency`
|
||||
: "New Agency";
|
||||
|
||||
const { data: createdAgency, error: agencyError } = (await admin
|
||||
.from("agencies")
|
||||
.insert({ name: defaultAgencyName })
|
||||
.select("id")
|
||||
.single()) as {
|
||||
data: Pick<Database["public"]["Tables"]["agencies"]["Row"], "id"> | null;
|
||||
error: { message: string } | null;
|
||||
};
|
||||
|
||||
if (agencyError || !createdAgency) {
|
||||
throw new Error(
|
||||
`Unable to create agency: ${agencyError?.message ?? "no row returned"}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { error: membershipError } = await admin.from("agency_members").insert({
|
||||
agency_id: createdAgency.id,
|
||||
user_id: userId,
|
||||
role: "owner",
|
||||
});
|
||||
|
||||
if (!membershipError) {
|
||||
return {
|
||||
agency_id: createdAgency.id,
|
||||
role: "owner" as const,
|
||||
};
|
||||
}
|
||||
|
||||
// If another request created membership first, fall back to a fresh read.
|
||||
const { data: retriedMembership } = (await supabase
|
||||
.from("agency_members")
|
||||
.select("agency_id, role")
|
||||
.eq("user_id", userId)
|
||||
.order("created_at", { ascending: true })
|
||||
.limit(1)
|
||||
.maybeSingle()) as { data: AgencyMemberSummary | null };
|
||||
|
||||
if (retriedMembership) {
|
||||
return retriedMembership;
|
||||
}
|
||||
|
||||
throw new Error("Unable to create agency membership");
|
||||
}
|
||||
|
||||
export async function getServerAgencyContextOrRedirect(): Promise<AgencyContext> {
|
||||
const supabase = createSupabaseServerClient();
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (!user) {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const membership = await getOrCreateAgencyMembership(user.id, user.email);
|
||||
|
||||
return {
|
||||
userId: user.id,
|
||||
agencyId: membership.agency_id,
|
||||
role: membership.role,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getRouteAgencyContextOrThrow(): Promise<AgencyContext> {
|
||||
const supabase = createSupabaseRouteClient();
|
||||
const db = supabase as any;
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
|
||||
if (!session?.user) {
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
|
||||
const { data: membership } = (await db
|
||||
.from("agency_members")
|
||||
.select("agency_id, role")
|
||||
.eq("user_id", session.user.id)
|
||||
.order("created_at", { ascending: true })
|
||||
.limit(1)
|
||||
.maybeSingle()) as { data: AgencyMemberSummary | null };
|
||||
|
||||
if (!membership) {
|
||||
throw new Error("No agency membership");
|
||||
}
|
||||
|
||||
return {
|
||||
userId: session.user.id,
|
||||
agencyId: membership.agency_id,
|
||||
role: membership.role,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user