- proxies table (migration 0095, port_id cascade), one per client/interest/yacht - service: get/set(upsert)/clear + resolveEffectiveProxy (yacht → interest → client precedence), port-scoped with entity-in-port guard - per-entity sub-resource routes (/clients|interests|yachts/[id]/proxy) reusing each entity's existing view/edit permission (no new permission resource) - 3 integration tests (CRUD/upsert, tenant guard, resolution precedence) Backend only — ProxyCard UI on the 3 detail pages to follow. tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
/**
|
|
* CM-9: shared GET/PUT/DELETE handlers for the per-entity proxy sub-resource
|
|
* (`/api/v1/{clients|interests|yachts}/[id]/proxy`). Each entity's route.ts
|
|
* binds these with its own permission resource so we reuse existing
|
|
* clients/interests/yachts gating instead of a new permission.
|
|
*/
|
|
|
|
import { NextResponse } from 'next/server';
|
|
|
|
import { type RouteHandler } from '@/lib/api/helpers';
|
|
import { parseBody } from '@/lib/api/route-helpers';
|
|
import { errorResponse } from '@/lib/errors';
|
|
import { clearProxy, getProxy, setProxy } from '@/lib/services/proxies.service';
|
|
import { setProxySchema, type ProxyEntityType } from '@/lib/validators/proxies';
|
|
|
|
export function makeProxyHandlers(entityType: ProxyEntityType) {
|
|
const getHandler: RouteHandler = async (req, ctx, params) => {
|
|
try {
|
|
const proxy = await getProxy(ctx.portId, entityType, params.id!);
|
|
return NextResponse.json({ data: proxy });
|
|
} catch (error) {
|
|
return errorResponse(error);
|
|
}
|
|
};
|
|
|
|
const putHandler: RouteHandler = async (req, ctx, params) => {
|
|
try {
|
|
const body = await parseBody(req, setProxySchema);
|
|
const proxy = await setProxy(ctx.portId, entityType, params.id!, body, {
|
|
userId: ctx.userId,
|
|
portId: ctx.portId,
|
|
ipAddress: ctx.ipAddress,
|
|
userAgent: ctx.userAgent,
|
|
});
|
|
return NextResponse.json({ data: proxy });
|
|
} catch (error) {
|
|
return errorResponse(error);
|
|
}
|
|
};
|
|
|
|
const deleteHandler: RouteHandler = async (req, ctx, params) => {
|
|
try {
|
|
await clearProxy(ctx.portId, entityType, params.id!, {
|
|
userId: ctx.userId,
|
|
portId: ctx.portId,
|
|
ipAddress: ctx.ipAddress,
|
|
userAgent: ctx.userAgent,
|
|
});
|
|
return new NextResponse(null, { status: 204 });
|
|
} catch (error) {
|
|
return errorResponse(error);
|
|
}
|
|
};
|
|
|
|
return { getHandler, putHandler, deleteHandler };
|
|
}
|