103 lines
3.5 KiB
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);
|
||
|
}
|