supersam/volumes/functions/push-unsubscribe/index.ts

105 lines
2.5 KiB
TypeScript

import { createServiceClient } from "../_shared/security.ts";
import {
getCorsHeaders,
jsonResponse,
preflightResponse,
readJsonBody,
} from "../_shared/security.ts";
const MAX_BODY_BYTES = 4 * 1024;
type UnsubscribeBody = {
endpoint?: string;
phone_normalized?: string;
};
Deno.serve(async (request) => {
if (request.method === "OPTIONS") {
return preflightResponse(request, "public");
}
if (request.method !== "POST") {
return jsonResponse({ ok: false, error: "Method not allowed" }, 405);
}
const corsHeaders = getCorsHeaders(request, "public");
if (!corsHeaders) {
return jsonResponse({ ok: false, error: "Origin not allowed" }, 403);
}
try {
const { body } = await readJsonBody<UnsubscribeBody>(request, {
maxBytes: MAX_BODY_BYTES,
});
const endpoint = String(body.endpoint || "").trim();
const phoneNormalized = String(body.phone_normalized || "").trim();
if (!endpoint) {
return jsonResponse(
{ ok: false, error: "endpoint is required" },
400,
corsHeaders,
);
}
if (!phoneNormalized) {
return jsonResponse(
{ ok: false, error: "phone_normalized is required" },
400,
corsHeaders,
);
}
const supabase = createServiceClient();
const now = new Date().toISOString();
const { data, error } = await supabase
.from("push_subscriptions")
.update({
is_active: false,
updated_at: now,
})
.eq("endpoint", endpoint)
.eq("phone_normalized", phoneNormalized)
.select("id, phone_normalized, endpoint, is_active, updated_at");
if (error) {
console.error("push-unsubscribe update error:", error);
return jsonResponse(
{ ok: false, error: "Database error", detail: error.message },
500,
corsHeaders,
);
}
const deactivatedCount = data?.length || 0;
return jsonResponse(
{
ok: true,
deactivated: deactivatedCount,
subscriptions: data,
},
200,
corsHeaders,
);
} catch (error) {
if (error instanceof Error && "status" in error) {
const httpError = error as { status: number; message: string };
return jsonResponse(
{ ok: false, error: httpError.message },
httpError.status,
corsHeaders,
);
}
return jsonResponse(
{
ok: false,
error: error instanceof Error ? error.message : "Unexpected error",
},
500,
corsHeaders,
);
}
});