mirror of
https://github.com/detleph/server.git
synced 2026-09-06 23:44:26 +02:00
patched issues found during testing
This commit is contained in:
@@ -20,7 +20,7 @@ const InitialDisciplineBody = z.object({
|
|||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
minTeamSize: z.number(),
|
minTeamSize: z.number(),
|
||||||
maxTeamSize: z.number(),
|
maxTeamSize: z.number(),
|
||||||
briefDescription: z.string(),
|
briefDescription: z.string().min(1),
|
||||||
fullDescription: z.string(),
|
fullDescription: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -29,9 +29,7 @@ const disciplineRefiner = [
|
|||||||
{ message: "The minTeamSize must be smaller or equal to the maxTeamSize" },
|
{ message: "The minTeamSize must be smaller or equal to the maxTeamSize" },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
const DisciplineBody = InitialDisciplineBody.partial({ briefDescription: true, fullDescription: true }).refine(
|
const DisciplineBody = InitialDisciplineBody.partial({ fullDescription: true }).refine(...disciplineRefiner);
|
||||||
...disciplineRefiner
|
|
||||||
);
|
|
||||||
const updateDisciplineBody = InitialDisciplineBody.partial().refine(...disciplineRefiner);
|
const updateDisciplineBody = InitialDisciplineBody.partial().refine(...disciplineRefiner);
|
||||||
|
|
||||||
const basicDiscipline = {
|
const basicDiscipline = {
|
||||||
@@ -158,17 +156,19 @@ export const createDiscipline = async (req: Request<{ eventPid: string }, {}, Cr
|
|||||||
name: DataType.STRING,
|
name: DataType.STRING,
|
||||||
minTeamSize: DataType.NUMBER,
|
minTeamSize: DataType.NUMBER,
|
||||||
maxTeamSize: DataType.NUMBER,
|
maxTeamSize: DataType.NUMBER,
|
||||||
|
briefDescription: DataType.STRING,
|
||||||
|
["fullDescription?"]: DataType.STRING,
|
||||||
},
|
},
|
||||||
result.error
|
result.error
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { name, minTeamSize, maxTeamSize } = result.data;
|
const { name, minTeamSize, maxTeamSize, briefDescription } = result.data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const discipline = await prisma.discipline.create({
|
const discipline = await prisma.discipline.create({
|
||||||
data: { name, minTeamSize, maxTeamSize, event: { connect: { pid: req.params.eventPid } } },
|
data: { name, minTeamSize, maxTeamSize, briefDescription, event: { connect: { pid: req.params.eventPid } } },
|
||||||
select: basicDiscipline,
|
select: basicDiscipline,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ export const deleteGroup = async (req: Request<DeleteGroupQueryParams>, res: Res
|
|||||||
const { pid } = req.params;
|
const { pid } = req.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
prisma.group.delete({ where: { pid } });
|
await prisma.group.delete({ where: { pid } });
|
||||||
|
|
||||||
return res.status(204).end();
|
return res.status(204).end();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ export const deleteOrganisation = async (req: Request<DeleteOrganisationQueryPar
|
|||||||
const { pid } = req.params;
|
const { pid } = req.params;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
prisma.organisation.delete({ where: { pid } });
|
await prisma.organisation.delete({ where: { pid } });
|
||||||
|
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ export async function assignParticipantToRole(req: Request<{ pid: string }>, res
|
|||||||
const { participantPid } = zBody.data;
|
const { participantPid } = zBody.data;
|
||||||
const rolePid = req.params.pid;
|
const rolePid = req.params.pid;
|
||||||
|
|
||||||
requireResponsibleForParticipant(req.teamleader, participantPid);
|
|
||||||
|
|
||||||
const schema = await prisma.role.findFirst({
|
const schema = await prisma.role.findFirst({
|
||||||
where: { pid: rolePid, team: { participants: { some: { pid: participantPid } } } },
|
where: { pid: rolePid, team: { participants: { some: { pid: participantPid } } } },
|
||||||
select: { participant: { select: { pid: true, firstName: true, lastName: true } } },
|
select: { participant: { select: { pid: true, firstName: true, lastName: true } } },
|
||||||
|
|||||||
@@ -24,8 +24,28 @@ interface CreateTeamBody {
|
|||||||
partGroupId: string;
|
partGroupId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const basicTeam = {
|
||||||
|
pid: true,
|
||||||
|
name: true,
|
||||||
|
discipline: { select: { pid: true } },
|
||||||
|
roles: {
|
||||||
|
select: {
|
||||||
|
pid: true,
|
||||||
|
schema: { select: { name: true } },
|
||||||
|
participant: { select: { pid: true } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
participants: {
|
||||||
|
select: {
|
||||||
|
pid: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const getTeams = async (req: Request, res: Response) => {
|
export const getTeams = async (req: Request, res: Response) => {
|
||||||
const teams = prisma.team.findMany({ select: { pid: true, name: true, disciplineId: true } });
|
const teams = await prisma.team.findMany({ select: basicTeam });
|
||||||
|
|
||||||
res.status(200).json(teams);
|
res.status(200).json(teams);
|
||||||
};
|
};
|
||||||
@@ -33,13 +53,9 @@ export const getTeams = async (req: Request, res: Response) => {
|
|||||||
export const getTeam = async (req: Request, res: Response) => {
|
export const getTeam = async (req: Request, res: Response) => {
|
||||||
const { pid } = req.params;
|
const { pid } = req.params;
|
||||||
|
|
||||||
const team = prisma.team.findUnique({
|
const team = await prisma.team.findUnique({
|
||||||
where: { pid },
|
where: { pid },
|
||||||
select: {
|
select: basicTeam,
|
||||||
disciplineId: true,
|
|
||||||
name: true,
|
|
||||||
pid: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).json(team);
|
res.status(200).json(team);
|
||||||
@@ -72,7 +88,7 @@ export const updateTeam = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const team = prisma.team.update({
|
const team = await prisma.team.update({
|
||||||
where: {
|
where: {
|
||||||
pid: body.pid,
|
pid: body.pid,
|
||||||
},
|
},
|
||||||
@@ -96,13 +112,7 @@ export const updateTeam = async (req: Request, res: Response) => {
|
|||||||
export const deleteTeam = async (req: Request, res: Response) => {
|
export const deleteTeam = async (req: Request, res: Response) => {
|
||||||
const { pid } = req.params;
|
const { pid } = req.params;
|
||||||
|
|
||||||
try {
|
await prisma.team.delete({ where: { pid } });
|
||||||
requireLeaderOfTeam(req.teamleader, pid);
|
|
||||||
} catch {
|
|
||||||
return res.status(401).json(createInsufficientPermissionsError("STANDARD"));
|
|
||||||
}
|
|
||||||
|
|
||||||
prisma.team.delete({ where: { pid } });
|
|
||||||
|
|
||||||
res.status(204).json("Welp its gone");
|
res.status(204).json("Welp its gone");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { createInsufficientPermissionsError, DataType, generateInvalidBodyError
|
|||||||
import { generateTeamleaderJWT, requireLeaderOfTeam } from "../Middleware/auth/teamleaderAuth";
|
import { generateTeamleaderJWT, requireLeaderOfTeam } from "../Middleware/auth/teamleaderAuth";
|
||||||
import { createRolesForTeam } from "./role.controller";
|
import { createRolesForTeam } from "./role.controller";
|
||||||
import { any, z } from "zod";
|
import { any, z } from "zod";
|
||||||
|
import { basicTeam } from "./team.controller";
|
||||||
|
|
||||||
const TeamBody = z.object({
|
const TeamBody = z.object({
|
||||||
teamName: z.string().min(1),
|
teamName: z.string().min(1),
|
||||||
@@ -70,13 +71,13 @@ export const register = async (req: Request<{}, {}, CreateTeamBody>, res: Respon
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO: maybe use returned amount of created use?
|
await createRolesForTeam(team.pid);
|
||||||
createRolesForTeam(team.pid);
|
|
||||||
|
|
||||||
const usid = nanoid();
|
const usid = nanoid();
|
||||||
|
|
||||||
(await mailClient).set(usid, team.pid);
|
(await mailClient).set(usid, team.pid);
|
||||||
|
|
||||||
|
// TODO: fix "eventname"
|
||||||
verificationMail(req.body.leaderEmail, "eventname", usid);
|
verificationMail(req.body.leaderEmail, "eventname", usid);
|
||||||
|
|
||||||
res.status(201).json({ type: "success", payload: { team } });
|
res.status(201).json({ type: "success", payload: { team } });
|
||||||
@@ -103,6 +104,7 @@ export const requestToken = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
(await mailClient).set(usid, team.pid);
|
(await mailClient).set(usid, team.pid);
|
||||||
|
|
||||||
|
// TODO: fix "eventname"
|
||||||
verificationMail(team.leaderEmail, "eventname", usid);
|
verificationMail(team.leaderEmail, "eventname", usid);
|
||||||
|
|
||||||
res.status(200).json({ type: "sucess", message: "Email sent!" });
|
res.status(200).json({ type: "sucess", message: "Email sent!" });
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export function notFoundHandler(req: Request, res: Response) {
|
|||||||
return res.status(404).json({
|
return res.status(404).json({
|
||||||
type: "error",
|
type: "error",
|
||||||
payload: {
|
payload: {
|
||||||
message: `The ${req.method} HTTP method is implemented for '${req.path}'`,
|
message: `The ${req.method} HTTP method is not implemented for '${req.path}'`,
|
||||||
_links: [
|
_links: [
|
||||||
{
|
{
|
||||||
rel: "root",
|
rel: "root",
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { requireAuthentication, requireConfiguredAuthentication } from "../Middl
|
|||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
teamRouter.post<"/:teamPid/participant/", { teamPid: string }>(
|
teamRouter.post<"/:teamPid/participants/", { teamPid: string }>(
|
||||||
"/:teamPid/participant/",
|
"/:teamPid/participants/",
|
||||||
requireAuthentication,
|
requireAuthentication,
|
||||||
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
||||||
createParticipant
|
createParticipant
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
import Express from "express";
|
import Express from "express";
|
||||||
import { assignParticipantToRole, getRolesForTeam } from "../Controllers/role.controller";
|
import { assignParticipantToRole, getRolesForTeam } from "../Controllers/role.controller";
|
||||||
|
import { requireAuthentication, requireConfiguredAuthentication } from "../Middleware/auth/auth";
|
||||||
|
|
||||||
const router = Express.Router();
|
const router = Express.Router();
|
||||||
|
|
||||||
//TO DO: maybe transfer getRolesForTeam to team router -> Seconded
|
//TO DO: maybe transfer getRolesForTeam to team router -> Seconded
|
||||||
router.get<"team/:teamPid/", { teamPid: string }>("team/:teamPid/", getRolesForTeam);
|
router.get<"team/:teamPid/", { teamPid: string }>(
|
||||||
|
"team/:teamPid/",
|
||||||
|
requireAuthentication,
|
||||||
|
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
||||||
|
getRolesForTeam
|
||||||
|
);
|
||||||
|
|
||||||
router.put<"/:pid/participant", { pid: string }>("/:pid/participant", assignParticipantToRole);
|
router.put<"/:pid/participant", { pid: string }>(
|
||||||
|
"/:pid/participant",
|
||||||
|
requireAuthentication,
|
||||||
|
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
||||||
|
assignParticipantToRole
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -6,9 +6,19 @@ import { deleteTeam, getTeam, getTeams, updateTeam } from "../Controllers/team.c
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.get("/", requireConfiguredAuthentication({ type: "admin", optional: false }), getTeams);
|
router.get("/", requireConfiguredAuthentication({ type: "admin", optional: false }), getTeams);
|
||||||
router.get("/:id", getTeam);
|
router.get(
|
||||||
|
"/:id",
|
||||||
|
requireAuthentication,
|
||||||
|
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
||||||
|
getTeam
|
||||||
|
);
|
||||||
|
|
||||||
router.put("/", requireTeamleaderAuthentication, updateTeam);
|
router.put("/", requireTeamleaderAuthentication, updateTeam);
|
||||||
router.delete<"/:pid/", { pid: string }>("/:pid/", requireAuthentication, requireTeamleaderAuthentication, deleteTeam);
|
router.delete<"/:pid/", { pid: string }>(
|
||||||
|
"/:pid/",
|
||||||
|
requireAuthentication,
|
||||||
|
requireConfiguredAuthentication({ optional: true, type: { admin: true, teamleader: true } }),
|
||||||
|
deleteTeam
|
||||||
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
+8
-2
@@ -14,7 +14,9 @@ import logger from "./Middleware/error/logger";
|
|||||||
import debugLogger from "./Middleware/debug/logger";
|
import debugLogger from "./Middleware/debug/logger";
|
||||||
import mediaRouter from "./Routes/media.routes";
|
import mediaRouter from "./Routes/media.routes";
|
||||||
import userRouter from "./Routes/user_auth.routes";
|
import userRouter from "./Routes/user_auth.routes";
|
||||||
import TeamRouter from "./Routes/team.routes";
|
import teamRouter from "./Routes/team.routes";
|
||||||
|
import roleRouter from "./Routes/role.routes";
|
||||||
|
import participantRouter from "./Routes/participant.routes";
|
||||||
import { notFoundHandler, rootHandler } from "./Middleware/error/defaultRoutes";
|
import { notFoundHandler, rootHandler } from "./Middleware/error/defaultRoutes";
|
||||||
|
|
||||||
// Set up async error handling
|
// Set up async error handling
|
||||||
@@ -87,7 +89,11 @@ async function main() {
|
|||||||
|
|
||||||
app.use("/api/users", userRouter);
|
app.use("/api/users", userRouter);
|
||||||
|
|
||||||
app.use("/api/teams", TeamRouter);
|
app.use("/api/teams", teamRouter);
|
||||||
|
|
||||||
|
app.use("/api/roles", roleRouter);
|
||||||
|
|
||||||
|
app.use("/api/participants", participantRouter);
|
||||||
|
|
||||||
app.get("/", rootHandler);
|
app.get("/", rootHandler);
|
||||||
app.get("/api", rootHandler);
|
app.get("/api", rootHandler);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ const sendMail = async (from: string, to: string, subject: string, text?: string
|
|||||||
export const verificationMail = async (to: string, eventName: string, verificationLink: string) => {
|
export const verificationMail = async (to: string, eventName: string, verificationLink: string) => {
|
||||||
const raw = mjml.getTemplate("emailVerification");
|
const raw = mjml.getTemplate("emailVerification");
|
||||||
|
|
||||||
|
// TODO: the process.env.DOMAIN is undefined in Development mode !!
|
||||||
verificationLink =
|
verificationLink =
|
||||||
"https://" + ("api." + process.env.DOMAIN ?? "localhost:3000/api") + "/users/verify/" + verificationLink;
|
"https://" + ("api." + process.env.DOMAIN ?? "localhost:3000/api") + "/users/verify/" + verificationLink;
|
||||||
const message = Handlebars.compile(raw);
|
const message = Handlebars.compile(raw);
|
||||||
|
|||||||
Reference in New Issue
Block a user