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); }