feat: extend PATCH /organization to accept logo upload and removal
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2ab1d8e044
commit
bb1b206aea
1 changed files with 49 additions and 12 deletions
|
|
@ -4,6 +4,7 @@ import { Hono } from "hono";
|
|||
import { createFactory } from "hono/factory";
|
||||
import { getOrganizationBillingState } from "../helpers/billing.js";
|
||||
import { createInvitedUser, getOrganizationPlan, MAX_TABLO_LIMIT } from "../helpers/helpers.js";
|
||||
import { uploadOrgIcons, deleteOrgIcons } from "../helpers/orgIcons.js";
|
||||
import type { AuthEnv } from "../types/app.types.js";
|
||||
|
||||
const factory = createFactory<AuthEnv>();
|
||||
|
|
@ -439,13 +440,8 @@ const getOrganization = factory.createHandlers(async (c) => {
|
|||
const updateOrganization = factory.createHandlers(async (c) => {
|
||||
const user = c.get("user");
|
||||
const supabase = c.get("supabase");
|
||||
const s3Client = c.get("s3_client");
|
||||
const body = await c.req.json();
|
||||
const rawName = typeof body?.name === "string" ? body.name : "";
|
||||
const name = rawName.trim();
|
||||
|
||||
if (name.length < 2 || name.length > 100) {
|
||||
return c.json({ error: "Organization name must be between 2 and 100 characters" }, 400);
|
||||
}
|
||||
|
||||
const { data: profile, error: profileError } = await supabase
|
||||
.from("profiles")
|
||||
|
|
@ -461,13 +457,54 @@ const updateOrganization = factory.createHandlers(async (c) => {
|
|||
return c.json({ error: "Temporary users cannot update organization settings" }, 403);
|
||||
}
|
||||
|
||||
const { error: updateError } = await supabase
|
||||
.from("organizations")
|
||||
.update({ name })
|
||||
.eq("id", profile.organization_id);
|
||||
const organizationId = profile.organization_id;
|
||||
const updateData: Record<string, unknown> = {};
|
||||
|
||||
if (updateError) {
|
||||
return c.json({ error: updateError.message }, 500);
|
||||
// Handle name update
|
||||
if (body?.name !== undefined) {
|
||||
const rawName = typeof body.name === "string" ? body.name : "";
|
||||
const name = rawName.trim();
|
||||
if (name.length < 2 || name.length > 100) {
|
||||
return c.json({ error: "Organization name must be between 2 and 100 characters" }, 400);
|
||||
}
|
||||
updateData.name = name;
|
||||
}
|
||||
|
||||
// Handle logo upload
|
||||
if (body?.logo !== undefined) {
|
||||
if (body.logo === null) {
|
||||
// Remove logo
|
||||
await deleteOrgIcons(s3Client, organizationId);
|
||||
updateData.logo_url = null;
|
||||
} else if (body.logo?.content && body.logo?.contentType) {
|
||||
const { content, contentType } = body.logo;
|
||||
|
||||
// Validate content type
|
||||
const allowedTypes = ["image/png", "image/jpeg", "image/webp"];
|
||||
if (!allowedTypes.includes(contentType)) {
|
||||
return c.json({ error: "Logo must be PNG, JPEG, or WebP" }, 400);
|
||||
}
|
||||
|
||||
const imageBuffer = Buffer.from(content, "base64");
|
||||
try {
|
||||
const basePath = await uploadOrgIcons(s3Client, organizationId, imageBuffer);
|
||||
updateData.logo_url = basePath;
|
||||
} catch (err: unknown) {
|
||||
const message = err instanceof Error ? err.message : "Failed to process logo";
|
||||
return c.json({ error: message }, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(updateData).length > 0) {
|
||||
const { error: updateError } = await supabase
|
||||
.from("organizations")
|
||||
.update(updateData)
|
||||
.eq("id", organizationId);
|
||||
|
||||
if (updateError) {
|
||||
return c.json({ error: updateError.message }, 500);
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({ message: "Organization updated successfully" });
|
||||
|
|
|
|||
Loading…
Reference in a new issue