Mitchell Magro 4f05061411 Fixed Build
2025-11-25 11:39:58 +01:00

155 lines
4.8 KiB
TypeScript

// app/api/users/[id]/route.ts
import { NextResponse } from "next/server";
const BE_BASE_URL = process.env.BE_BASE_URL || "http://localhost:5000";
const COOKIE_NAME = "auth_token";
// Field mapping: snake_case input -> { snake_case for data, PascalCase for fields }
// Matches API metadata field_names.users mapping
const FIELD_MAPPING: Record<string, { dataKey: string; fieldName: string }> = {
id: { dataKey: "id", fieldName: "ID" },
email: { dataKey: "email", fieldName: "Email" },
first_name: { dataKey: "first_name", fieldName: "FirstName" },
last_name: { dataKey: "last_name", fieldName: "LastName" },
username: { dataKey: "username", fieldName: "Username" },
phone: { dataKey: "phone", fieldName: "Phone" },
job_title: { dataKey: "job_title", fieldName: "JobTitle" },
password: { dataKey: "password", fieldName: "Password" },
temp_link: { dataKey: "temp_link", fieldName: "TempLink" },
temp_password: { dataKey: "temp_password", fieldName: "TempPassword" },
temp_expiry: { dataKey: "temp_expiry", fieldName: "TempExpiry" },
groups: { dataKey: "groups", fieldName: "Groups" },
merchants: { dataKey: "merchants", fieldName: "Merchants" },
enabled: { dataKey: "enabled", fieldName: "Enabled" },
};
/**
* Transforms frontend snake_case data to backend format
* with data (snake_case) and fields (PascalCase) arrays
*/
function transformUserUpdateData(updates: Record<string, unknown>): {
data: Record<string, unknown>;
fields: string[];
} {
const data: Record<string, unknown> = {};
const fields: string[] = [];
for (const [key, value] of Object.entries(updates)) {
// Skip undefined/null values
if (value === undefined || value === null) {
continue;
}
const mapping = FIELD_MAPPING[key];
if (mapping) {
// Use the dataKey for the data object (snake_case)
data[mapping.dataKey] = value;
// Use the fieldName for the fields array (PascalCase)
fields.push(mapping.fieldName);
} else {
// If no mapping exists, use the key as-is (for backwards compatibility)
data[key] = value;
// Convert snake_case to PascalCase for fields
const pascalCase = key
.split("_")
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join("");
fields.push(pascalCase);
}
}
return { data, fields };
}
export async function PUT(
request: Request,
context: { params: Promise<{ id: string }> }
) {
try {
const { id } = await context.params;
const body = await request.json();
// Transform the request body to match backend format
const transformedBody = transformUserUpdateData(body);
// Get the auth token from cookies
const { cookies } = await import("next/headers");
const cookieStore = await cookies();
const token = cookieStore.get(COOKIE_NAME)?.value;
if (!token) {
return NextResponse.json(
{ message: "Missing Authorization header" },
{ status: 401 }
);
}
// According to swagger: /api/v1/users/{id}
const response = await fetch(`${BE_BASE_URL}/api/v1/users/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(transformedBody),
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (err: unknown) {
const errorMessage =
err instanceof Error ? err.message : "Unknown error occurred";
return NextResponse.json(
{ message: "Internal server error", error: errorMessage },
{ status: 500 }
);
}
}
export async function DELETE(
_request: Request,
context: { params: Promise<{ id: string }> }
) {
try {
const { id } = await context.params;
const { cookies } = await import("next/headers");
const cookieStore = await cookies();
const token = cookieStore.get(COOKIE_NAME)?.value;
if (!token) {
return NextResponse.json(
{ message: "Missing Authorization header" },
{ status: 401 }
);
}
// According to swagger: /api/v1/users/{id}
const response = await fetch(`${BE_BASE_URL}/api/v1/users/${id}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${token}`,
},
});
// Some backends return empty body for DELETE; handle safely
let data: unknown = null;
try {
data = await response.json();
} catch {
data = { success: response.ok };
}
return NextResponse.json(data ?? { success: response.ok }, {
status: response.status,
});
} catch (err: unknown) {
console.error("Proxy DELETE /api/v1/users/{id} error:", err);
const errorMessage =
err instanceof Error ? err.message : "Unknown error occurred";
return NextResponse.json(
{ message: "Internal server error", error: errorMessage },
{ status: 500 }
);
}
}