Files
2026-06-09 12:34:57 -07:00

208 lines
5.5 KiB
TypeScript

import { z } from "zod";
import { registry } from "../registry.js";
import { bearer, json, multipart, okJson, okJsonNoData, standardErrors } from "../helpers.js";
import {
loginValidation,
registrationBodyValidation,
recoveryValidation,
recoveryTokenBodyValidation,
newPasswordValidation,
} from "@/api/validation/authValidation.js";
import {
getUserByIdParamValidation,
editUserByIdParamValidation,
editUserByIdBodyValidation,
editUserPasswordByIdBodyValidation,
createUserBodyValidation,
editUserBodyValidation,
userResponseSchema,
} from "@/api/validation/userValidation.js";
const tags = ["auth"];
const userExample = {
_id: "65f1c2a4d8b9e0123456789a",
firstName: "Ada",
lastName: "Lovelace",
email: "ada@example.com",
role: ["admin"],
teamId: "65f1c2a4d8b9e01234567890",
createdAt: "2026-04-01T10:00:00.000Z",
updatedAt: "2026-04-15T14:30:00.000Z",
};
const userObject = userResponseSchema.openapi("User", { example: userExample });
const authPayload = z
.object({
user: userObject,
token: z.string().optional(),
})
.openapi("AuthPayload", {
example: {
user: userExample,
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
},
});
registry.registerPath({
method: "post",
path: "/auth/register",
tags,
summary: "Register a new user (first user becomes superadmin)",
request: { body: { content: multipart(registrationBodyValidation.shape, "profileImage") } },
responses: { "200": okJson(authPayload), ...standardErrors },
});
registry.registerPath({
method: "post",
path: "/auth/login",
tags,
summary: "Log in",
request: {
body: {
content: json(loginValidation, { email: "ada@example.com", password: "S3cure!Passw0rd" }),
},
},
responses: {
"200": okJson(authPayload, "OK", {
user: {
_id: "65f1c2a4d8b9e0123456789a",
firstName: "Ada",
lastName: "Lovelace",
email: "ada@example.com",
role: ["admin"],
teamId: "65f1c2a4d8b9e01234567890",
createdAt: "2026-04-01T10:00:00.000Z",
updatedAt: "2026-04-15T14:30:00.000Z",
},
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
}),
"401": { description: "Invalid credentials", content: json(z.object({ success: z.literal(false), msg: z.string() })) },
"500": standardErrors["500"],
},
});
registry.registerPath({
method: "post",
path: "/auth/recovery/request",
tags,
summary: "Request a password recovery email",
request: { body: { content: json(recoveryValidation, { email: "ada@example.com" }) } },
responses: { "200": okJsonNoData(), "500": standardErrors["500"] },
});
registry.registerPath({
method: "post",
path: "/auth/recovery/validate",
tags,
summary: "Validate a password recovery token",
request: { body: { content: json(recoveryTokenBodyValidation) } },
responses: { "200": okJsonNoData(), "500": standardErrors["500"] },
});
registry.registerPath({
method: "post",
path: "/auth/recovery/reset",
tags,
summary: "Reset password using a recovery token",
request: { body: { content: json(newPasswordValidation) } },
responses: { "200": okJsonNoData(), "500": standardErrors["500"] },
});
registry.registerPath({
method: "get",
path: "/auth/users/superadmin",
tags,
summary: "Check whether a superadmin user exists",
responses: { "200": okJson(z.object({ superAdminExists: z.boolean() })), "500": standardErrors["500"] },
});
registry.registerPath({
method: "get",
path: "/auth/users",
tags,
summary: "List all users (admin/superadmin)",
security: bearer,
responses: { "200": okJson(z.array(userObject)), ...standardErrors },
});
registry.registerPath({
method: "post",
path: "/auth/users",
tags,
summary: "Create a new user (superadmin)",
security: bearer,
request: { body: { content: multipart(createUserBodyValidation.shape, "profileImage") } },
responses: { "201": okJson(userObject, "User created"), ...standardErrors },
});
registry.registerPath({
method: "get",
path: "/auth/users/{userId}",
tags,
summary: "Get a user by id",
security: bearer,
request: { params: getUserByIdParamValidation },
responses: {
"200": okJson(userObject),
"404": { description: "User not found", content: json(z.object({ success: z.literal(false), msg: z.string() })) },
...standardErrors,
},
});
registry.registerPath({
method: "patch",
path: "/auth/users/{userId}",
tags,
summary: "Edit a user (superadmin)",
security: bearer,
request: {
params: editUserByIdParamValidation,
body: { content: json(editUserByIdBodyValidation) },
},
responses: { "200": okJsonNoData(), ...standardErrors },
});
registry.registerPath({
method: "patch",
path: "/auth/users/{userId}/password",
tags,
summary: "Change a user's password (superadmin)",
security: bearer,
request: {
params: editUserByIdParamValidation,
body: { content: json(editUserPasswordByIdBodyValidation) },
},
responses: { "200": okJsonNoData(), ...standardErrors },
});
registry.registerPath({
method: "delete",
path: "/auth/users/{userId}",
tags,
summary: "Delete a user (admin/superadmin)",
security: bearer,
request: { params: getUserByIdParamValidation },
responses: { "200": okJsonNoData(), ...standardErrors },
});
registry.registerPath({
method: "patch",
path: "/auth/user",
tags,
summary: "Edit the currently authenticated user",
security: bearer,
request: { body: { content: multipart(editUserBodyValidation.shape, "profileImage") } },
responses: { "200": okJson(userObject), ...standardErrors },
});
registry.registerPath({
method: "delete",
path: "/auth/user",
tags,
summary: "Delete the currently authenticated user",
security: bearer,
responses: { "200": okJsonNoData(), ...standardErrors },
});