[create-pull-request] push formatted files

This commit is contained in:
Stefan-5422
2022-06-07 18:22:55 +00:00
committed by GitHub
parent 05d4c08ec2
commit 1a6c780de5
12 changed files with 222 additions and 210 deletions
+3 -1
View File
@@ -29,7 +29,9 @@ export const getAllAdmins = async (req: Request, res: Response) => {
} }
// TODO: Add exception handling // TODO: Add exception handling
const users = await prisma.admin.findMany({ select: { pid: true, name: true, permission_level: true, groups: { select: { pid: true } } } }); const users = await prisma.admin.findMany({
select: { pid: true, name: true, permission_level: true, groups: { select: { pid: true } } },
});
res.status(200).json({ res.status(200).json({
type: "success", type: "success",
+8 -1
View File
@@ -168,7 +168,14 @@ export const createDiscipline = async (req: Request<{ eventPid: string }, {}, Cr
try { try {
const discipline = await prisma.discipline.create({ const discipline = await prisma.discipline.create({
data: { name, minTeamSize, maxTeamSize, briefDescription, fullDescription, event: { connect: { pid: req.params.eventPid } } }, data: {
name,
minTeamSize,
maxTeamSize,
briefDescription,
fullDescription,
event: { connect: { pid: req.params.eventPid } },
},
select: basicDiscipline, select: basicDiscipline,
}); });
+16 -16
View File
@@ -38,7 +38,7 @@ const detailedGroup = {
organisation: { select: { pid: true, name: true } }, organisation: { select: { pid: true, name: true } },
participants: { select: { pid: true, firstName: true, lastName: true } }, participants: { select: { pid: true, firstName: true, lastName: true } },
admins: { select: { pid: true, name: true } }, admins: { select: { pid: true, name: true } },
} };
export const _getAllGroups = async (res: Response, organisationId: string | undefined) => { export const _getAllGroups = async (res: Response, organisationId: string | undefined) => {
const groups = await prisma.group.findMany({ const groups = await prisma.group.findMany({
@@ -88,12 +88,12 @@ export const getGroup = async (req: Request<GetGroupQueryParams>, res: Response)
where: { pid }, where: { pid },
select: req.auth?.isAuthenticated select: req.auth?.isAuthenticated
? { ? {
pid: true, pid: true,
name: true, name: true,
organisation: { select: { pid: true, name: true } }, organisation: { select: { pid: true, name: true } },
admins: { select: { pid: true, name: true } }, admins: { select: { pid: true, name: true } },
participants: { select: { pid: true } }, participants: { select: { pid: true } },
} }
: basicGroup, : basicGroup,
}); });
@@ -112,15 +112,15 @@ export const getGroup = async (req: Request<GetGroupQueryParams>, res: Response)
}, },
...(req.auth?.isAuthenticated ...(req.auth?.isAuthenticated
? { ? {
admins: group.admins?.map((admin) => ({ admins: group.admins?.map((admin) => ({
...admin, ...admin,
_links: [{ rel: "self", type: "GET", href: `/api/admins/${admin.pid}` }], _links: [{ rel: "self", type: "GET", href: `/api/admins/${admin.pid}` }],
})), })),
participants: group.participants?.map((participant) => ({ participants: group.participants?.map((participant) => ({
...participant, ...participant,
_links: [{ rel: "self", type: "GET", href: `/api/participant/${participant.pid}` }], _links: [{ rel: "self", type: "GET", href: `/api/participant/${participant.pid}` }],
})), })),
} }
: {}), : {}),
}, },
}, },
-1
View File
@@ -224,7 +224,6 @@ export const linkMedia = async (req: Request<{ pid: string }, {}, { mediaPid: st
throw e; throw e;
} }
}; };
export const unlinkMedia = async (req: Request<{ pid: string; mediaPid: string }>, res: Response) => { export const unlinkMedia = async (req: Request<{ pid: string; mediaPid: string }>, res: Response) => {
+4 -6
View File
@@ -64,13 +64,13 @@ export const createParticipant = async (req: Request<{ teamPid: string }>, res:
try { try {
const discipline = await prisma.team.findUnique({ const discipline = await prisma.team.findUnique({
where: { pid: teamPid }, where: { pid: teamPid },
select: { discipline: true } select: { discipline: true },
}); });
const maxteamsize = discipline?.discipline.maxTeamSize; const maxteamsize = discipline?.discipline.maxTeamSize;
const userCount = await prisma.participant.count({ const userCount = await prisma.participant.count({
where: { team: { pid: teamPid } } where: { team: { pid: teamPid } },
}); });
if (maxteamsize == userCount) { if (maxteamsize == userCount) {
@@ -88,7 +88,7 @@ export const createParticipant = async (req: Request<{ teamPid: string }>, res:
select: returnedParticipant, select: returnedParticipant,
}); });
return res.status(201).json({ type: "success", payload: { participant }, }); return res.status(201).json({ type: "success", payload: { participant } });
} catch (e) { } catch (e) {
if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") {
return res return res
@@ -176,9 +176,7 @@ export const deleteParticipant = async (req: Request<{ pid: string }>, res: Resp
}; };
export async function getGroupByParticipantPid(partPid: string) { export async function getGroupByParticipantPid(partPid: string) {
const parti = ( const parti = (await prisma.participant.findUnique({ where: { pid: partPid }, select: { group: true } }))?.group.pid;
await prisma.participant.findUnique({ where: { pid: partPid }, select: { group: true } })
)?.group.pid;
if (!parti) { if (!parti) {
throw new NotFoundError("participant", partPid); throw new NotFoundError("participant", partPid);
+5 -1
View File
@@ -106,7 +106,11 @@ export async function assignParticipantToRole(req: Request<{ pid: string }>, res
} }
try { try {
const schema = await prisma.role.update({ where: { pid }, data: { participant: { connect: { pid: participantPid } } }, select: detailedRole }); const schema = await prisma.role.update({
where: { pid },
data: { participant: { connect: { pid: participantPid } } },
select: detailedRole,
});
return res.status(200).json({ return res.status(200).json({
type: "success", type: "success",
+7 -6
View File
@@ -119,7 +119,7 @@ export const deleteTeam = async (req: Request, res: Response) => {
} }
if (req.auth?.permission_level == "STANDARD") { if (req.auth?.permission_level == "STANDARD") {
throw new AuthError("STANDARD Admins are not allowed to delete Teams!") throw new AuthError("STANDARD Admins are not allowed to delete Teams!");
} }
try { try {
@@ -137,7 +137,7 @@ export const deleteTeam = async (req: Request, res: Response) => {
export async function checkTeamExistence(teamPid: string) { export async function checkTeamExistence(teamPid: string) {
const teamCount = await prisma.team.count({ const teamCount = await prisma.team.count({
where: { pid: teamPid, } where: { pid: teamPid },
}); });
if (teamCount == 0) { if (teamCount == 0) {
throw new NotFoundError("team", teamPid); throw new NotFoundError("team", teamPid);
@@ -145,13 +145,14 @@ export async function checkTeamExistence(teamPid: string) {
} }
export async function getGroupsByTeamPid(teamPid: string) { export async function getGroupsByTeamPid(teamPid: string) {
const team = ( const team = await prisma.team.findUnique({
await prisma.team.findUnique({ where: { pid: teamPid }, select: { participants: { select: { group: true } } } }) where: { pid: teamPid },
); select: { participants: { select: { group: true } } },
});
let groups: string[] = []; let groups: string[] = [];
team?.participants.forEach(participant => { team?.participants.forEach((participant) => {
groups.push(participant.group.pid); groups.push(participant.group.pid);
}); });
+105 -105
View File
@@ -18,82 +18,42 @@ export const getBearerToken = (authorization: string) => authorization.slice(7);
const _requireAdminAuthentication = const _requireAdminAuthentication =
(config: { optional?: Boolean; controlled?: Boolean } = { optional: false, controlled: false }) => (config: { optional?: Boolean; controlled?: Boolean } = { optional: false, controlled: false }) =>
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
if (!JWT_SECRET) { if (!JWT_SECRET) {
throw new Error("JWT_SECRET not set"); throw new Error("JWT_SECRET not set");
}
const { authorization } = req.headers;
if (!authorization) {
if (config.optional) {
return false;
} }
const { authorization } = req.headers; return res.status(403).send({
type: "error",
payload: {
message: "The requeset did not include the Authorization header",
},
});
}
if (!authorization) { if (!verifyAuthorizationFormat(authorization)) {
if (config.optional) { return res.status(400).send({
return false; type: "error",
} payload: {
message: "Malformed Authorization header",
format: "Bearer <token>",
},
});
}
return res.status(403).send({ let token_payload_: string | JwtPayload;
type: "error",
payload: {
message: "The requeset did not include the Authorization header",
},
});
}
if (!verifyAuthorizationFormat(authorization)) { try {
return res.status(400).send({ token_payload_ = jwt.verify(getBearerToken(authorization), JWT_SECRET);
type: "error", } catch (e) {
payload: { if (e instanceof JsonWebTokenError) {
message: "Malformed Authorization header",
format: "Bearer <token>",
},
});
}
let token_payload_: string | JwtPayload;
try {
token_payload_ = jwt.verify(getBearerToken(authorization), JWT_SECRET);
} catch (e) {
if (e instanceof JsonWebTokenError) {
return res.status(403).json({
type: "error",
payload: {
message: "Token could not be verified; It might be expired",
},
});
}
throw e;
}
const token_payload = token_payload_ as AuthJWTPayload;
if (!token_payload.permission_level || !token_payload.pid || !token_payload.revision) {
if (typeof (token_payload as unknown as TeamleaderJWTPayload).team === "string") {
if (config.controlled) {
return false;
}
throw new AuthError("Teamleader authentication is not supported for this operation!");
}
throw new AuthError("The token did not include the required information!");
}
const { pid, revision } = token_payload;
let db_revision = await authClient.get(pid);
if (db_revision === null) {
// Load the revision ID from the main DB and cache it in redis
const user = await prisma.admin.findUnique({ where: { pid }, select: { revision: true } });
if (user) {
db_revision = user.revision.toISOString();
await authClient.set(pid, db_revision);
}
}
if (revision !== db_revision || !revision || !db_revision) {
return res.status(403).json({ return res.status(403).json({
type: "error", type: "error",
payload: { payload: {
@@ -102,22 +62,62 @@ const _requireAdminAuthentication =
}); });
} }
req.auth = { throw e;
isAuthenticated: true, }
pid: token_payload.pid,
name: token_payload.name,
permission_level: token_payload.permission_level,
groups: token_payload.groups,
revision: token_payload.revision,
};
if (!config.controlled) { const token_payload = token_payload_ as AuthJWTPayload;
next();
if (!token_payload.permission_level || !token_payload.pid || !token_payload.revision) {
if (typeof (token_payload as unknown as TeamleaderJWTPayload).team === "string") {
if (config.controlled) {
return false;
}
throw new AuthError("Teamleader authentication is not supported for this operation!");
} }
return true; throw new AuthError("The token did not include the required information!");
}
const { pid, revision } = token_payload;
let db_revision = await authClient.get(pid);
if (db_revision === null) {
// Load the revision ID from the main DB and cache it in redis
const user = await prisma.admin.findUnique({ where: { pid }, select: { revision: true } });
if (user) {
db_revision = user.revision.toISOString();
await authClient.set(pid, db_revision);
}
}
if (revision !== db_revision || !revision || !db_revision) {
return res.status(403).json({
type: "error",
payload: {
message: "Token could not be verified; It might be expired",
},
});
}
req.auth = {
isAuthenticated: true,
pid: token_payload.pid,
name: token_payload.name,
permission_level: token_payload.permission_level,
groups: token_payload.groups,
revision: token_payload.revision,
}; };
if (!config.controlled) {
next();
}
return true;
};
export const requireAuthentication = _requireAdminAuthentication({ optional: false, controlled: false }); export const requireAuthentication = _requireAdminAuthentication({ optional: false, controlled: false });
type AuthType = "admin" | "teamleader"; type AuthType = "admin" | "teamleader";
@@ -144,37 +144,37 @@ function getAuthTypes(type: AuthType | AuthTypeConfig): AuthType[] {
export const requireConfiguredAuthentication = export const requireConfiguredAuthentication =
(config: AuthConfiguration = { optional: false, type: "admin" }) => (config: AuthConfiguration = { optional: false, type: "admin" }) =>
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const types = getAuthTypes(config.type); const types = getAuthTypes(config.type);
const optional = config.optional; const optional = config.optional;
let adminFinished = false; let adminFinished = false;
let teamleaderFinished = false; let teamleaderFinished = false;
if (types.includes("admin")) { if (types.includes("admin")) {
adminFinished = Boolean(await _requireAdminAuthentication({ optional: true, controlled: true })(req, res, next)); adminFinished = Boolean(await _requireAdminAuthentication({ optional: true, controlled: true })(req, res, next));
if (adminFinished) { if (adminFinished) {
return next(); return next();
}
} }
}
if (types.includes("teamleader")) { if (types.includes("teamleader")) {
teamleaderFinished = Boolean( teamleaderFinished = Boolean(
_requireTeamleaderAuthentication({ optional: true, controlled: true })(req, res, next) _requireTeamleaderAuthentication({ optional: true, controlled: true })(req, res, next)
); );
if (teamleaderFinished) { if (teamleaderFinished) {
return next(); return next();
}
} }
}
if (!config.optional) { if (!config.optional) {
throw new AuthError("No sufficient authorization was provided for this operation"); throw new AuthError("No sufficient authorization was provided for this operation");
} }
next(); next();
}; };
export function requireResponsibleForGroups(auth: AuthJWTPayload | undefined, groupPids: string[] | string) { export function requireResponsibleForGroups(auth: AuthJWTPayload | undefined, groupPids: string[] | string) {
if (auth?.permission_level === "ELEVATED") { if (auth?.permission_level === "ELEVATED") {
@@ -182,7 +182,7 @@ export function requireResponsibleForGroups(auth: AuthJWTPayload | undefined, gr
} }
if (Array.isArray(groupPids)) { if (Array.isArray(groupPids)) {
groupPids.forEach(gr => { groupPids.forEach((gr) => {
if (auth?.groups.includes(gr)) { if (auth?.groups.includes(gr)) {
return; return;
} }
+47 -47
View File
@@ -26,63 +26,63 @@ export function generateTeamleaderJWT(teamleader: Team) {
export const _requireTeamleaderAuthentication = export const _requireTeamleaderAuthentication =
(config: { optional: Boolean; controlled: Boolean } = { optional: false, controlled: false }) => (config: { optional: Boolean; controlled: Boolean } = { optional: false, controlled: false }) =>
(req: Request, res: Response, next: NextFunction) => { (req: Request, res: Response, next: NextFunction) => {
if (!JWT_SECRET) { if (!JWT_SECRET) {
throw new Error("JWT_SECRET not set"); throw new Error("JWT_SECRET not set");
}
const { authorization } = req.headers;
if (!authorization) {
if (config.optional) {
return false;
} }
const { authorization } = req.headers; return res.status(403).send({
type: "error",
payload: {
message:
"The request did not include the Authorization header (Only the team leader can perform this operation)",
},
});
}
if (!authorization) { if (!verifyAuthorizationFormat(authorization)) {
if (config.optional) { return res.status(400).send({
return false; type: "error",
} payload: {
message: "Malformed Authorization header",
format: "Bearer <token>",
},
});
}
return res.status(403).send({ try {
const token_payload = jwt.verify(getBearerToken(authorization), JWT_SECRET) as TeamleaderJWTPayload;
req.teamleader = {
isAuthenticated: true,
team: token_payload.team,
};
if (!config.controlled) {
next();
}
return true;
} catch (e) {
if (e instanceof JsonWebTokenError) {
return res.status(403).json({
type: "error", type: "error",
payload: { payload: {
message: message: "Token could not be verified; It might be expired",
"The request did not include the Authorization header (Only the team leader can perform this operation)",
}, },
}); });
} }
if (!verifyAuthorizationFormat(authorization)) { throw e;
return res.status(400).send({ }
type: "error", };
payload: {
message: "Malformed Authorization header",
format: "Bearer <token>",
},
});
}
try {
const token_payload = jwt.verify(getBearerToken(authorization), JWT_SECRET) as TeamleaderJWTPayload;
req.teamleader = {
isAuthenticated: true,
team: token_payload.team,
};
if (!config.controlled) {
next();
}
return true;
} catch (e) {
if (e instanceof JsonWebTokenError) {
return res.status(403).json({
type: "error",
payload: {
message: "Token could not be verified; It might be expired",
},
});
}
throw e;
}
};
export const requireTeamleaderAuthentication = _requireTeamleaderAuthentication({ optional: false, controlled: false }); export const requireTeamleaderAuthentication = _requireTeamleaderAuthentication({ optional: false, controlled: false });
+1 -7
View File
@@ -1,12 +1,6 @@
import Express from "express"; import Express from "express";
import { string } from "zod"; import { string } from "zod";
import { import { addEvent, deleteEvent, getAllEvents, getEvent, updateEvent } from "../Controllers/event.controller";
addEvent,
deleteEvent,
getAllEvents,
getEvent,
updateEvent,
} from "../Controllers/event.controller";
import { requireAuthentication } from "../Middleware/auth/auth"; import { requireAuthentication } from "../Middleware/auth/auth";
const router = Express.Router(); const router = Express.Router();
+25 -18
View File
@@ -1,7 +1,14 @@
import express from "express"; import express from "express";
import fileUpload from "express-fileupload"; import fileUpload from "express-fileupload";
import { requireAuthentication } from "../Middleware/auth/auth"; import { requireAuthentication } from "../Middleware/auth/auth";
import { deleteMedia, getAllMedia, getMediaMeta, linkMedia, unlinkMedia, uploadImage } from "../Controllers/media.controller"; import {
deleteMedia,
getAllMedia,
getMediaMeta,
linkMedia,
unlinkMedia,
uploadImage,
} from "../Controllers/media.controller";
import eventRouter from "./event.routes"; import eventRouter from "./event.routes";
import disciplineRouter from "./discipline.routes"; import disciplineRouter from "./discipline.routes";
import roleSchemaRouter from "./role_schema.routes"; import roleSchemaRouter from "./role_schema.routes";
@@ -19,28 +26,28 @@ router.get("/:pid/meta", getMediaMeta);
router.delete("/:pid", requireAuthentication, deleteMedia); router.delete("/:pid", requireAuthentication, deleteMedia);
eventRouter.post<"/:pid/media", { pid: string }>( eventRouter.post<"/:pid/media", { pid: string }>("/:pid/media", requireAuthentication, linkMedia);
"/:pid/media", requireAuthentication, linkMedia
eventRouter.delete<"/:pid/media/:mediaPid", { pid: string; mediaPid: string }>(
"/:pid/media/:mediaPid",
requireAuthentication,
unlinkMedia
); );
eventRouter.delete<"/:pid/media/:mediaPid", { pid: string, mediaPid: string }>( disciplineRouter.post<"/:pid/media", { pid: string }>("/:pid/media", requireAuthentication, linkMedia);
"/:pid/media/:mediaPid", requireAuthentication, unlinkMedia
disciplineRouter.delete<"/:pid/media/:mediaPid", { pid: string; mediaPid: string }>(
"/:pid/media/:mediaPid",
requireAuthentication,
unlinkMedia
); );
disciplineRouter.post<"/:pid/media", { pid: string }>( roleSchemaRouter.post<"/:pid/media", { pid: string }>("/:pid/media", requireAuthentication, linkMedia);
"/:pid/media", requireAuthentication, linkMedia
);
disciplineRouter.delete<"/:pid/media/:mediaPid", { pid: string, mediaPid: string }>( roleSchemaRouter.delete<"/:pid/media/:mediaPid", { pid: string; mediaPid: string }>(
"/:pid/media/:mediaPid", requireAuthentication, unlinkMedia "/:pid/media/:mediaPid",
); requireAuthentication,
unlinkMedia
roleSchemaRouter.post<"/:pid/media", { pid: string }>(
"/:pid/media", requireAuthentication, linkMedia
);
roleSchemaRouter.delete<"/:pid/media/:mediaPid", { pid: string, mediaPid: string }>(
"/:pid/media/:mediaPid", requireAuthentication, unlinkMedia
); );
export default router; export default router;
+1 -1
View File
@@ -17,4 +17,4 @@ teamRouter.get<"/:pid/roles", { pid: string }>(
getRolesForTeam getRolesForTeam
); );
export default router; export default router;