107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
import type { Application, RequestHandler, Response } from "express";
|
|
import { Router } from "express";
|
|
import { z } from "zod/v4";
|
|
|
|
import {
|
|
DirectoryMembershipCommandSchema,
|
|
DirectoryMembershipQuerySchema,
|
|
} from "../../../common/directory-memberships";
|
|
import type { DirectoryMembershipUseCases } from "../../application/directory-membership.use-cases";
|
|
import { buildDirectoryMembershipResponse } from "../../application/directory-membership-response.builder";
|
|
|
|
const ScopeSchema = z.strictObject({ companyId: z.uuid() });
|
|
const AssetScopeSchema = ScopeSchema.extend({ assetId: z.uuid() });
|
|
|
|
function fail(response: Response, code: string) {
|
|
response
|
|
.status(code === "INVALID_REQUEST" ? 400 : code.endsWith("NOT_FOUND") ? 404 : 409)
|
|
.json({ code, requestId: response.getHeader("x-request-id") });
|
|
}
|
|
|
|
export function registerDirectoryMembershipRoutes(
|
|
app: Application,
|
|
service: DirectoryMembershipUseCases,
|
|
authenticate: RequestHandler
|
|
) {
|
|
const router = Router();
|
|
|
|
router.get("/:companyId", (request, response, next) => {
|
|
const scope = ScopeSchema.safeParse(request.params);
|
|
const query = DirectoryMembershipQuerySchema.safeParse(request.query);
|
|
|
|
if (!(scope.success && query.success)) {
|
|
fail(response, "INVALID_REQUEST");
|
|
|
|
return;
|
|
}
|
|
service
|
|
.list(scope.data.companyId, query.data)
|
|
.then((result) => {
|
|
if (!result.isSuccess) {
|
|
fail(response, result.error.code);
|
|
|
|
return;
|
|
}
|
|
response.json({
|
|
memberships: result.data.memberships.map(buildDirectoryMembershipResponse),
|
|
nextCursor: result.data.nextCursor,
|
|
});
|
|
})
|
|
.catch(next);
|
|
});
|
|
router.get("/:companyId/:assetId/current", (request, response, next) => {
|
|
const scope = AssetScopeSchema.safeParse(request.params);
|
|
|
|
if (!(scope.success && z.strictObject({}).safeParse(request.query).success)) {
|
|
fail(response, "INVALID_REQUEST");
|
|
|
|
return;
|
|
}
|
|
service
|
|
.list(scope.data.companyId, { assetId: scope.data.assetId, pageSize: 1 })
|
|
.then((result) => {
|
|
if (!result.isSuccess) {
|
|
fail(response, result.error.code);
|
|
|
|
return;
|
|
}
|
|
const item = result.data.memberships[0];
|
|
|
|
response.json({ membership: item ? buildDirectoryMembershipResponse(item) : null });
|
|
})
|
|
.catch(next);
|
|
});
|
|
router.post("/:companyId/:assetId", (request, response, next) => {
|
|
const scope = AssetScopeSchema.safeParse(request.params);
|
|
const body = DirectoryMembershipCommandSchema.safeParse(request.body);
|
|
const actor = z
|
|
.object({ userId: z.uuid() })
|
|
.safeParse("session" in request ? request.session : undefined);
|
|
|
|
if (
|
|
!(
|
|
scope.success &&
|
|
body.success &&
|
|
actor.success &&
|
|
z.strictObject({}).safeParse(request.query).success
|
|
)
|
|
) {
|
|
fail(response, "INVALID_REQUEST");
|
|
|
|
return;
|
|
}
|
|
service
|
|
.execute(scope.data.companyId, scope.data.assetId, body.data, actor.data.userId)
|
|
.then((result) => {
|
|
if (!result.isSuccess) {
|
|
fail(response, result.error.code);
|
|
|
|
return;
|
|
}
|
|
response.json({ membership: buildDirectoryMembershipResponse(result.data) });
|
|
})
|
|
.catch(next);
|
|
});
|
|
app.use("/api/asset-directory-memberships", authenticate, router);
|
|
}
|