Add good validation to all existing endpoints

This commit is contained in:
Kevin Puig
2025-09-27 14:17:15 -04:00
parent b9982b626f
commit 27807357ac
3 changed files with 82 additions and 23 deletions

View File

@@ -1,11 +1,30 @@
import { Hono } from "hono";
import { fetchAllUsers, fetchUserData, createNewUser } from "../controller/userController";
import { createUserSchema } from "../validators/userValidator";
import { createUserSchema, queryAllUsersByInstanceId, queryUserByIdSchema } from "../validators/userValidator";
import { zValidator } from "@hono/zod-validator";
import { describeRoute, resolver } from "hono-openapi";
const actions = new Hono();
actions.get("user/:id", async (c) => {
actions.get("user/:id",
describeRoute({
description: "Get user by id",
responses: {
200: {
description: "Success getting user",
content: {
"application/json": { schema: resolver(queryUserByIdSchema) }
}
},
404: {
description: "User id not found",
content: {
"application/json": { schema: resolver(queryUserByIdSchema) }
}
}
}
}),
zValidator('param', queryUserByIdSchema),
async (c) => {
const id = c.req.param("id");
const userData = await fetchUserData(id);
if (userData) {
@@ -13,10 +32,24 @@ actions.get("user/:id", async (c) => {
} else {
return c.json({ error: "User not found" }, 404);
}
});
}
);
actions.get("user", async (c) => {
const instanceId = c.req.query("instance_id");
actions.get("user",
describeRoute({
description: "Get all users by instance id",
responses: {
200: {
description: "Success getting all users in instance",
content: {
"application/json": { schema: resolver(queryAllUsersByInstanceId) }
}
}
}
}),
zValidator('query', queryAllUsersByInstanceId),
async (c) => {
const instanceId = c.req.query("instanceId");
if (!instanceId) {
return c.json({ error: "No instance id provided" }, 400);
}
@@ -27,7 +60,8 @@ actions.get("user", async (c) => {
} else {
return c.json({ error: "Error getting all users from instance" }, 500);
}
});
}
);
actions.post(
"user",
@@ -39,6 +73,12 @@ actions.post(
content: {
'application/json': { schema: resolver(createUserSchema) },
},
},
400: {
description: "Bad request (user exists)",
content: {
'application/json': { schema: resolver(createUserSchema) }
}
}
}
}),
@@ -47,6 +87,9 @@ actions.post(
try {
const data = await c.req.json();
const newUser = await createNewUser(data);
if (!newUser) {
return c.json({ error: "User already exists" }, 400);
}
return c.json(newUser, 201);
} catch (error) {
return c.json({ error: "Error creating user" }, 500);

View File

@@ -10,6 +10,10 @@ import { CreateUserInput } from '../validators/userValidator';
const prisma = new PrismaClient();
export async function createUser(data: CreateUserInput) {
if (await prisma.user.count({ where: { username: data.username }}) >= 1) {
return null;
}
return await prisma.user.create({
data: {
username: data.username,
@@ -111,9 +115,13 @@ export async function getAllUsersFrom(instanceId: string): Promise<
| null
> {
try {
const instances = await prisma.instance.findMany();
if (!instances) {
throw new Error("could not get all instances");
const instances = await prisma.instance.count({
where: {
id: instanceId
}
})
if (instances < 1) {
throw new Error("could not find given instance id");
}
const users = await prisma.user.findMany({

View File

@@ -1,5 +1,13 @@
import { z } from 'zod'
export const queryUserByIdSchema = z.object({
id: z.uuidv7()
})
export const queryAllUsersByInstanceId = z.object({
instanceId: z.uuidv7()
})
export const createUserSchema = z.object({
username: z.string().min(3).max(30),
nickname: z.string().min(1).max(30).optional(),