feat(api): complete phase 2.4 control plane
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import type {
|
||||
UpstreamRequest,
|
||||
UpstreamResponse,
|
||||
} from '../../application/connections/upstream-session-client.js';
|
||||
import type { TransportResponse } from './safe-instance-transport.js';
|
||||
import { UpstreamError } from './upstream-error.js';
|
||||
|
||||
export interface SafeUpstreamTransport {
|
||||
get(url: string): Promise<TransportResponse>;
|
||||
post(
|
||||
url: string,
|
||||
headers: Readonly<Record<string, string>>,
|
||||
body: string,
|
||||
): Promise<TransportResponse>;
|
||||
}
|
||||
export class SafeUpstreamGateway {
|
||||
constructor(private readonly options: { readonly transport: SafeUpstreamTransport }) {}
|
||||
async request(request: UpstreamRequest): Promise<UpstreamResponse> {
|
||||
const url = new URL(request.url);
|
||||
if (url.protocol !== 'https:') throw new UpstreamError('UPSTREAM_INSECURE_AUTH');
|
||||
if (request.method !== 'POST') throw new UpstreamError('UPSTREAM_REQUEST_INVALID');
|
||||
if (request.url.endsWith('/api/auth/login')) {
|
||||
if (typeof request.secret !== 'string' || request.body !== '[REDACTED]')
|
||||
throw new UpstreamError('UPSTREAM_REQUEST_INVALID');
|
||||
return this.options.transport.post(
|
||||
request.url,
|
||||
request.headers,
|
||||
JSON.stringify({ password: request.secret }),
|
||||
);
|
||||
}
|
||||
if (request.url.endsWith('/api/auth/logout')) {
|
||||
if (request.secret !== undefined || request.body !== undefined)
|
||||
throw new UpstreamError('UPSTREAM_REQUEST_INVALID');
|
||||
return this.options.transport.post(request.url, request.headers, '');
|
||||
}
|
||||
throw new UpstreamError('UPSTREAM_REQUEST_INVALID');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user