- House.adminId / House.inviteCode (migration Prisma) - house.service: createHouse, joinHouse, leaveCurrentHouse (transfert d'admin ou suppression du foyer si dernier membre), deleteHouse (admin-only), removeMember (admin-only) - house.routes: POST /house, POST /house/join, POST /house/leave, DELETE /house/current, DELETE /house/members/:memberId - GET/PATCH /house/current renvoient désormais membres + admin + code
110 lines
3.4 KiB
TypeScript
110 lines
3.4 KiB
TypeScript
import { HttpError } from "@batch-cooking/error-tools";
|
|
import { wrapAsyncHandler } from "@batch-cooking/express-tools";
|
|
import {
|
|
ErrorCode,
|
|
createHouseSchema,
|
|
joinHouseSchema,
|
|
renameHouseSchema,
|
|
} from "@batch-cooking/shared";
|
|
import { Router } from "express";
|
|
import { type AuthLocals, requireAuth } from "../../middlewares/require-auth.js";
|
|
import {
|
|
createHouse,
|
|
deleteHouse,
|
|
getCurrentHouse,
|
|
joinHouse,
|
|
leaveCurrentHouse,
|
|
removeMember,
|
|
renameHouse,
|
|
} from "./house.service.js";
|
|
|
|
/** Router mounted at `/house` in app.ts. Every route requires a session — a household is per-user (via their profile), never public. */
|
|
export const houseRouter = Router();
|
|
|
|
houseRouter.get(
|
|
"/current",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (_req, res) => {
|
|
const house = await getCurrentHouse(res.locals.userProfile.houseId);
|
|
res.status(200).json(house);
|
|
}),
|
|
);
|
|
|
|
/** The household step of the profile journey (onboarding wizard and the `/parametres/foyer` settings page both call this) — renaming, open to any member. */
|
|
houseRouter.patch(
|
|
"/current",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (req, res) => {
|
|
const input = renameHouseSchema.parse(req.body);
|
|
const house = await renameHouse(res.locals.userProfile.houseId, input.name);
|
|
res.status(200).json(house);
|
|
}),
|
|
);
|
|
|
|
/** Creates a new household for a profile that doesn't have one yet — the "create" half of the optional household step. */
|
|
houseRouter.post(
|
|
"/",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (req, res) => {
|
|
const input = createHouseSchema.parse(req.body);
|
|
const house = await createHouse(
|
|
res.locals.userProfile.id,
|
|
res.locals.userProfile.houseId,
|
|
input.name,
|
|
);
|
|
res.status(201).json(house);
|
|
}),
|
|
);
|
|
|
|
/** Joins an existing household by invite code — the "join" half of the optional household step. */
|
|
houseRouter.post(
|
|
"/join",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (req, res) => {
|
|
const input = joinHouseSchema.parse(req.body);
|
|
const house = await joinHouse(
|
|
res.locals.userProfile.id,
|
|
res.locals.userProfile.houseId,
|
|
input.inviteCode,
|
|
);
|
|
res.status(200).json(house);
|
|
}),
|
|
);
|
|
|
|
/** Removes the caller from their own household — see `deleteHouse` below for removing the household itself. */
|
|
houseRouter.post(
|
|
"/leave",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (_req, res) => {
|
|
await leaveCurrentHouse(res.locals.userProfile.id, res.locals.userProfile.houseId);
|
|
res.status(204).end();
|
|
}),
|
|
);
|
|
|
|
/** Deletes the household entirely — every member loses it. Admin-only, see `house.service.ts`. */
|
|
houseRouter.delete(
|
|
"/current",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (_req, res) => {
|
|
await deleteHouse(res.locals.userProfile.id, res.locals.userProfile.houseId);
|
|
res.status(204).end();
|
|
}),
|
|
);
|
|
|
|
/** Removes one specific member from the caller's household. Admin-only, see `house.service.ts`. */
|
|
houseRouter.delete(
|
|
"/members/:memberId",
|
|
requireAuth,
|
|
wrapAsyncHandler<unknown, AuthLocals>(async (req, res) => {
|
|
const memberId = Number(req.params.memberId);
|
|
if (!Number.isInteger(memberId)) {
|
|
throw new HttpError(400, ErrorCode.VALIDATION_ERROR, "memberId must be an integer");
|
|
}
|
|
const house = await removeMember(
|
|
res.locals.userProfile.id,
|
|
res.locals.userProfile.houseId,
|
|
memberId,
|
|
);
|
|
res.status(200).json(house);
|
|
}),
|
|
);
|