- Store and display original substitution type text - Treat "eigenverantwortliches Arbeiten" as cancellation
276 lines
7.1 KiB
JavaScript
276 lines
7.1 KiB
JavaScript
import Prisma from "@prisma/client";
|
|
const prisma = new Prisma.PrismaClient();
|
|
|
|
import {
|
|
applyKey,
|
|
hasPermission,
|
|
listPermissions,
|
|
revokeKey,
|
|
} from "./permission.js";
|
|
|
|
// Get info API endpoint (/api/info)
|
|
// Returns information about the requesting session
|
|
export async function getInfo(req, res) {
|
|
// If server has auth disabled
|
|
if (!req.locals.session) {
|
|
res.send({
|
|
authenticated: true,
|
|
appliedKeys: [],
|
|
permissions: [],
|
|
});
|
|
return;
|
|
}
|
|
|
|
const session = await prisma.session.findUnique({
|
|
where: {
|
|
token: req.locals.session,
|
|
},
|
|
include: {
|
|
appliedKeys: {
|
|
select: {
|
|
key: true,
|
|
permissions: true,
|
|
validUntil: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.send({
|
|
authenticated: true,
|
|
appliedKeys: session.appliedKeys,
|
|
permissions: await listPermissions(session.token),
|
|
});
|
|
}
|
|
|
|
// Put and Delete key API endpoints (/api/key)
|
|
// Applies or revokes a key from the requesting user's session
|
|
export async function putKey(req, res) {
|
|
if (await applyKey(req.locals.session, req.query.key)) {
|
|
res.status(200).send();
|
|
} else {
|
|
res.status(400).send({
|
|
success: false,
|
|
error: "invalid_key",
|
|
message: "This key does not exist",
|
|
});
|
|
}
|
|
}
|
|
|
|
export async function deleteKey(req, res) {
|
|
if (await revokeKey(req.locals.session, req.query.key)) {
|
|
res.status(200).send();
|
|
} else {
|
|
res.status(400).send();
|
|
}
|
|
}
|
|
|
|
// Get timetable API endpoint (/api/timetable)
|
|
// Returns timetable data for requested class if available
|
|
export async function getTimetable(req, res) {
|
|
if (!req.query.class) {
|
|
res.status(400).send({
|
|
success: false,
|
|
error: "missing_parameter",
|
|
message: "No class parameter provided",
|
|
});
|
|
return;
|
|
}
|
|
const requestedClass = req.query.class.toLowerCase();
|
|
const timetables = await prisma.timetable.findMany({
|
|
where: {
|
|
class: requestedClass,
|
|
},
|
|
orderBy: {
|
|
updatedAt: "desc",
|
|
},
|
|
});
|
|
const times = await prisma.time.findMany();
|
|
res.send({
|
|
timetables,
|
|
times,
|
|
});
|
|
}
|
|
|
|
// Edit timetable API endpoint (/api/timetable)
|
|
// Updates a remote timetable with the requested data
|
|
export async function putTimetable(req, res) {
|
|
const timetableId = parseInt(req.query.id);
|
|
const data = req.body.data;
|
|
if (
|
|
!(await hasPermission(req.locals.session, "timetable.update", timetableId))
|
|
) {
|
|
res.status(401).send({
|
|
success: false,
|
|
error: "missing_permission",
|
|
message: "You don't have permission to update this timetable!",
|
|
});
|
|
return;
|
|
}
|
|
|
|
await prisma.timetable.update({
|
|
where: {
|
|
id: timetableId,
|
|
},
|
|
data: {
|
|
data,
|
|
title: req.body.title,
|
|
},
|
|
});
|
|
res.status(201).send();
|
|
}
|
|
|
|
// Helper function for converting a date string
|
|
// (eg. "2022-06-02" or "1654128000000") to a
|
|
// unix timestamp
|
|
function convertToDate(dateQuery) {
|
|
var date;
|
|
if (dateQuery.match(/^[0-9]+$/) != null) date = parseInt(dateQuery);
|
|
else date = dateQuery;
|
|
date = new Date(date).setUTCHours(0, 0, 0, 0);
|
|
return new Date(date);
|
|
}
|
|
|
|
// Get substitutions API endpoint (/api/substitutions)
|
|
// Returns all known substitutions for requested date / class
|
|
// If no class is supplied, all substitutions are returned
|
|
export async function getSubstitutions(req, res) {
|
|
const requestedClass = (req.query.class || "").toLowerCase();
|
|
var from, to, date;
|
|
// Check if from or to date is set in request
|
|
if (req.query.from && req.query.to) {
|
|
from = convertToDate(req.query.from);
|
|
to = convertToDate(req.query.to);
|
|
} else if (req.query.date) {
|
|
date = convertToDate(req.query.date);
|
|
}
|
|
|
|
const prismaOptions = {
|
|
where: {
|
|
removed: false,
|
|
},
|
|
orderBy: {
|
|
lesson: "asc",
|
|
},
|
|
};
|
|
if (requestedClass) {
|
|
prismaOptions.where.class = { has: requestedClass };
|
|
}
|
|
// Choose which date to use in database query
|
|
if (from && to) {
|
|
prismaOptions.where.date = {
|
|
gte: from,
|
|
lte: to,
|
|
};
|
|
} else if (date) {
|
|
prismaOptions.where.date = date;
|
|
} else {
|
|
// Default to all substitutions for today and in the future
|
|
prismaOptions.where.date = {
|
|
gte: new Date(new Date().setUTCHours(0, 0, 0, 0)),
|
|
};
|
|
}
|
|
|
|
const rawSubstitutions = await prisma.substitution.findMany(prismaOptions);
|
|
const substitutions = rawSubstitutions.map((element) => {
|
|
const substitution = {
|
|
id: element.id,
|
|
class: element.class,
|
|
type: element.type,
|
|
rawType: element.rawType,
|
|
lesson: element.lesson,
|
|
date: new Date(element.date).getTime(),
|
|
notes: element.notes,
|
|
teacher: element.teacher,
|
|
change: {},
|
|
};
|
|
if (element.changedRoom) substitution.change.room = element.changedRoom;
|
|
if (element.changedTeacher)
|
|
substitution.change.teacher = element.changedTeacher;
|
|
if (element.changedSubject)
|
|
substitution.change.subject = element.changedSubject;
|
|
return substitution;
|
|
});
|
|
res.send(substitutions);
|
|
}
|
|
|
|
// Get history API endpoint (/api/history)
|
|
// Returns history of changes for all substituions in the date range
|
|
// for the requested class if supplied
|
|
export async function getHistory(req, res) {
|
|
const requestedClass = (req.query.class || "").toLowerCase();
|
|
var from, to, date;
|
|
// Check if from or to date is set in request
|
|
if (req.query.from && req.query.to) {
|
|
from = convertToDate(req.query.from);
|
|
to = convertToDate(req.query.to);
|
|
} else if (req.query.date) {
|
|
date = convertToDate(req.query.date);
|
|
}
|
|
|
|
const prismaOptions = {
|
|
where: {
|
|
substitution: {},
|
|
},
|
|
include: {
|
|
substitution: true,
|
|
},
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
};
|
|
if (requestedClass) {
|
|
prismaOptions.where.substitution.class = { has: requestedClass };
|
|
}
|
|
// Choose which date to use in database query
|
|
if (from && to) {
|
|
prismaOptions.where.substitution.date = {
|
|
gte: from,
|
|
lte: to,
|
|
};
|
|
} else if (date) {
|
|
prismaOptions.where.substitution.date = date;
|
|
} else {
|
|
// Default to history of all substitutions for today and in the future
|
|
prismaOptions.where.substitution.date = {
|
|
gte: new Date(new Date().setUTCHours(0, 0, 0, 0)),
|
|
};
|
|
}
|
|
|
|
const rawChanges = await prisma.substitutionChange.findMany(prismaOptions);
|
|
const changes = rawChanges.map((element) => {
|
|
return {
|
|
id: element.id,
|
|
type: element.type,
|
|
class: element.substitution.class,
|
|
substitutionId: element.substitutionId,
|
|
lesson: element.substitution.lesson,
|
|
updatedAt: new Date(element.createdAt).getTime(),
|
|
date: new Date(element.substitution.date).getTime(),
|
|
teacher: element.teacher,
|
|
change: element.changes,
|
|
notes: element.notes,
|
|
parseEventId: element.parseEventId,
|
|
};
|
|
});
|
|
res.send(changes);
|
|
}
|
|
|
|
// Get classes API endpoints (/api/classes)
|
|
// Get all available classes where timetable and
|
|
// substitutions can be requested for
|
|
export async function getClasses(_req, res) {
|
|
const classes = await prisma.class.findMany({
|
|
select: {
|
|
name: true,
|
|
regex: false,
|
|
},
|
|
orderBy: {
|
|
name: "asc",
|
|
},
|
|
});
|
|
// Only return the name of the class
|
|
const classList = classes.map((element) => element.name);
|
|
res.send(classList);
|
|
}
|