teacher-tools/api/source/api_modules/classroom_compliance/util.d

103 lines
3.5 KiB
D

module api_modules.classroom_compliance.util;
import api_modules.classroom_compliance.model;
import api_modules.auth;
import db;
import ddbc : Connection;
import handy_httpd;
import std.datetime;
/**
* Gets a Classroom-Compliance class from an HTTP request's path parameters,
* as well as a given user that the class should belong to.
* Params:
* ctx = The request context.
* conn = The database connection to use.
* user = The user who the class belongs to.
* Returns: The class that was found, or a 404 status exception is thrown.
*/
ClassroomComplianceClass getClassOrThrow(in HttpRequestContext ctx, Connection conn, in User user) {
ulong classId = ctx.request.getPathParamAs!ulong("classId");
return findOne(
conn,
"SELECT * FROM classroom_compliance_class WHERE user_id = ? AND id = ?",
&ClassroomComplianceClass.parse,
user.id, classId
).orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND));
}
/**
* Gets a Classroom-Compliance student from an HTTP request's path parameters,
* as well as a given user that the student should belong to.
* Params:
* ctx = The request context.
* conn = The database connection to use.
* user = The user who the student belongs to.
* Returns: The student that was found, or a 404 status exception is thrown.
*/
ClassroomComplianceStudent getStudentOrThrow(in HttpRequestContext ctx, Connection conn, in User user) {
ulong classId = ctx.request.getPathParamAs!ulong("classId");
ulong studentId = ctx.request.getPathParamAs!ulong("studentId");
string query = "
SELECT s.*
FROM classroom_compliance_student s
LEFT JOIN classroom_compliance_class c ON s.class_id = c.id
WHERE s.id = ? AND s.class_id = ? AND c.user_id = ?
";
return findOne(
conn,
query,
&ClassroomComplianceStudent.parse,
studentId,
classId,
user.id
).orElseThrow(() => new HttpStatusException(HttpStatus.NOT_FOUND));
}
struct DateRange {
Date from;
Date to;
}
/**
* Helper function to parse a date range from a request's "from" and "to"
* parameters, because this is used commonly for entry-related functions.
* Params:
* ctx = The request context.
* maxDays = The maximum date range length.
* Returns: The date range that was parsed.
*/
DateRange parseDateRangeParams(in HttpRequestContext ctx, uint maxDays = 10) {
SysTime now = Clock.currTime();
Date toDate = Date(now.year, now.month, now.day);
Date fromDate = toDate - days(4);
if (ctx.request.queryParams.contains("to")) {
try {
toDate = Date.fromISOExtString(ctx.request.queryParams.getFirst("to").orElse(""));
} catch (DateTimeException e) {
throw new HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid \"to\" date.");
}
}
if (ctx.request.queryParams.contains("from")) {
try {
fromDate = Date.fromISOExtString(ctx.request.queryParams.getFirst("from").orElse(""));
} catch (DateTimeException e) {
throw new HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid \"from\" date.");
}
}
if (fromDate > toDate) {
throw new HttpStatusException(
HttpStatus.BAD_REQUEST,
"Invalid date range. From-date must be less than or equal to the to-date."
);
}
if (toDate - fromDate > days(maxDays)) {
throw new HttpStatusException(
HttpStatus.BAD_REQUEST,
"Date range is too big."
);
}
return DateRange(fromDate, toDate);
}