Add maintenance mode endpoint for Vercel deployments
Create `api/admin/platform/maintenance.ts` to handle maintenance mode logic as a Vercel serverless function, including GET and POST requests for enabling/disabling and admin verification via Supabase. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: eb559abf-e967-427e-a938-a9f28fc6407c Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/qPXTzuE Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
ba650c5116
commit
688cfff89a
1 changed files with 106 additions and 0 deletions
106
api/admin/platform/maintenance.ts
Normal file
106
api/admin/platform/maintenance.ts
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import type { VercelRequest, VercelResponse } from "@vercel/node";
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
|
||||
const supabaseUrl = process.env.VITE_SUPABASE_URL || "";
|
||||
const supabaseServiceRole = process.env.SUPABASE_SERVICE_ROLE || "";
|
||||
|
||||
let maintenanceModeCache: boolean | null = null;
|
||||
|
||||
const ADMIN_ROLES = ["admin", "super_admin", "staff", "owner"];
|
||||
|
||||
async function verifyAdmin(token: string): Promise<boolean> {
|
||||
if (!supabaseUrl || !supabaseServiceRole) return false;
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceRole);
|
||||
|
||||
try {
|
||||
const { data: { user }, error } = await supabase.auth.getUser(token);
|
||||
if (error || !user) return false;
|
||||
|
||||
const { data: roles } = await supabase
|
||||
.from("user_roles")
|
||||
.select("role")
|
||||
.eq("user_id", user.id);
|
||||
|
||||
if (!roles) return false;
|
||||
|
||||
return roles.some(r => ADMIN_ROLES.includes(r.role?.toLowerCase()));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function handler(req: VercelRequest, res: VercelResponse) {
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
|
||||
const supabase = supabaseUrl && supabaseServiceRole
|
||||
? createClient(supabaseUrl, supabaseServiceRole)
|
||||
: null;
|
||||
|
||||
if (req.method === "GET") {
|
||||
try {
|
||||
if (supabase) {
|
||||
const { data, error } = await supabase
|
||||
.from("platform_settings")
|
||||
.select("value")
|
||||
.eq("key", "maintenance_mode")
|
||||
.single();
|
||||
|
||||
if (!error && data) {
|
||||
const isEnabled = data.value === true || data.value === "true";
|
||||
maintenanceModeCache = isEnabled;
|
||||
return res.json({ maintenance_mode: isEnabled });
|
||||
}
|
||||
}
|
||||
|
||||
const envMaintenance = process.env.MAINTENANCE_MODE === "true";
|
||||
return res.json({ maintenance_mode: maintenanceModeCache ?? envMaintenance });
|
||||
} catch (e) {
|
||||
const envMaintenance = process.env.MAINTENANCE_MODE === "true";
|
||||
return res.json({ maintenance_mode: maintenanceModeCache ?? envMaintenance });
|
||||
}
|
||||
}
|
||||
|
||||
if (req.method === "POST") {
|
||||
const authHeader = req.headers.authorization;
|
||||
const token = authHeader?.replace("Bearer ", "");
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({ error: "Unauthorized" });
|
||||
}
|
||||
|
||||
const isAdmin = await verifyAdmin(token);
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ error: "Forbidden - Admin access required" });
|
||||
}
|
||||
|
||||
const { maintenance_mode } = req.body;
|
||||
|
||||
if (typeof maintenance_mode !== "boolean") {
|
||||
return res.status(400).json({ error: "maintenance_mode must be a boolean" });
|
||||
}
|
||||
|
||||
try {
|
||||
if (supabase) {
|
||||
const { error } = await supabase
|
||||
.from("platform_settings")
|
||||
.upsert(
|
||||
{ key: "maintenance_mode", value: maintenance_mode, updated_at: new Date().toISOString() },
|
||||
{ onConflict: "key" }
|
||||
);
|
||||
|
||||
if (error) {
|
||||
console.error("[Maintenance] DB error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
maintenanceModeCache = maintenance_mode;
|
||||
return res.json({ maintenance_mode, success: true });
|
||||
} catch (e) {
|
||||
maintenanceModeCache = maintenance_mode;
|
||||
return res.json({ maintenance_mode, success: true });
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
Loading…
Reference in a new issue