Roadbound-BRR/supabase/functions/org-update/index.ts

76 lines
2.2 KiB
TypeScript

import { fail, handleOptions, json } from "../_shared/http.ts";
import { createServiceClient, requireUser, slugify } from "../_shared/supabase.ts";
Deno.serve(async (req) => {
const preflight = handleOptions(req);
if (preflight) return preflight;
if (req.method !== "POST") return fail("Method not allowed", 405);
const { user, error: userError } = await requireUser(req);
if (!user) return fail(userError ?? "Unauthorized", 401);
let body: {
organization_id?: string;
name?: string;
slug?: string;
icon_url?: string | null;
};
try {
body = await req.json();
} catch {
return fail("Invalid JSON body");
}
const organizationId = (body.organization_id ?? "").trim();
if (!organizationId) return fail("organization_id is required");
const name = body.name?.trim();
const iconUrl = body.icon_url === null ? null : body.icon_url?.trim();
if ((name == null || name.length === 0) && body.icon_url === undefined) {
return fail("name or icon_url is required");
}
const serviceClient = createServiceClient();
const { data: member, error: memberError } = await serviceClient
.from("organization_members")
.select("role")
.eq("organization_id", organizationId)
.eq("user_id", user.id)
.maybeSingle();
if (memberError) return fail(memberError.message, 400);
if (!member || !["owner", "admin"].includes(member.role)) {
return fail("forbidden", 403);
}
const patch: {
name?: string;
slug?: string;
icon_url?: string | null;
} = {};
if (name != null && name.length > 0) {
const slug = slugify((body.slug ?? "").trim() || name);
if (!slug) return fail("slug is invalid");
patch.name = name;
patch.slug = slug;
}
if (body.icon_url !== undefined) {
patch.icon_url = iconUrl && iconUrl.length > 0 ? iconUrl : null;
}
const { data: organization, error: updateError } = await serviceClient
.from("organizations")
.update(patch)
.eq("id", organizationId)
.select("id, name, slug, icon_url, owner_user_id, created_at")
.single();
if (updateError) {
if (updateError.code === "23505") return fail("slug is already taken", 409);
return fail(updateError.message, 400);
}
return json({ organization });
});