def activate_account(token: str): """Activates the account (while not authenticated) Parameters ---------- token : str The activation token Returns ------- dict The view response """ student = Student.verify_activation_token(token) if student is None: return error("That is an expired or incorrect link."), 400 else: if request.form["password_confirmation"] == request.form["password"]: if student.activate() and student.set_password( request.form["password"]): logger.info(f"Student {student._id} activated their account") return response(["Account activated!", "Password set!"]), 200 else: return error("Unknown error while activating account"), 400 else: return response(["Passwords don't match!"]), 400 db.students.update({"id": ObjectId(student._id)}, {"$set": { "activated": True }}) return response(["Account activated!"]), 200
def register_courses(): """Adds a course to the system. Returns ------- dict Flashes, course data from the form """ flashes = list() try: if Course.get_by_department_number(request.form["number"]): course = Course(request.form["department"], request.form["number"], request.form["name"]) else: return error("Course already exists"), 400 except KeyError: return error("Not all fields satisfied."), 400 if Admin.add_course(course=course): logger.info(f"Course {request.form['number']} added") flashes.append("Course added!") return response(flashes), 200 else: flashes.append("There was a problem adding your course") return response(flashes), 400
def get_calendar_events(): """Gets dictionary of calendar events for teacher Returns ------- dict The view response """ req_data = request.get_json() if req_data: title = req_data["title"] start = req_data["start"] end = req_data["end"] color = req_data["color"] url = req_data["url"] newEvent = { "title": title, "start": start, "end": end, "color": color, "url": url, } teacherDict = current_user.to_dict() teacher = Teacher.get_by_email(teacherDict["email"]) current_user.add_calendar_event(teacher.id, newEvent) events = current_user.get_calendar() return response(data={"events": events})
def add_assignment(): """Adds new assignment for the class Returns ------- dict The view response """ request.form["assigned_to"].choices = current_user.get_class_names() try: file_list = get_existing_assignment_files() new_assignment = Assignment( date_assigned=datetime.utcnow(), assigned_by=current_user.ID, assigned_to=request.form["assigned_to"], due_by=request.form["due_by"], title=request.form["title"], content=request.form["content"], filenames=file_list, estimated_time=request.form["estimated_time"], # weight=request.form['weight'] ) Course.get_by_id( request.form["assigned_to"]).add_assignment(new_assignment) logger.info(f"Assignment {request.form['title']} added") return response(flashes=["Assignment sent!"]) except KeyError: return error("Not all fields satisfied"), 400
def get_info_for_new_course(): """Gets department and teacher info for adding a new course to the database. Returns ------- dict Flashes, department and teacher data from the database """ flashes = list() try: departments = db.courses.find({}, {"department": 1, "_id": 0}) teachers = db.courses.find({}, { "name": 1, "email": 1, "department": 1, "_id": 0 }) except: return ( error( "Unknown error while getting info for departments and teachers" ), 400, ) return response(flashes, { "departments": departments, "teachers": teachers }), 200
def password_reset(token: str): """Resets the password (while not authenticated) Parameters ---------- token : str The reset token Returns ------- dict The view response """ if current_user.is_authenticated: return error( f"Wrong route, use {url_for('auth.change_password')}."), 303 user = User.verify_reset_token(token) if user is None: return error("That is an expired or incorrect link."), 410 user = User.from_dict(user) try: new_password = request.form["new_password"] user.password = new_password if not user.add(): return error("Unknown error while changing the password."), 500 except KeyError: return error("Not all fields satisfied"), 400 else: return response(["Password changed"]), 200
def get_schedule_assignments(): """Gets name and dates for assignments Returns ------- dict The view response """ assignments = current_user.get_assignments() events = [] for assignment in assignments: assignment_data = { "title": assignment.title, "date": assignment.due_by } events.append(assignment_data) # Dummy event for testing dummy_data = [{ "title": "Test assignment", "date": "2020-08-09", }] events.append(dummy_data) return response(data={"events": events})
def view_submissions_by_assignment(course_id: str, assignment_id: str): """Collects all submissions for a specific assignment of a class Parameters ------- course_id: str The course ID to look up in the database assignment_id: str The assignment ID to look up in the database Returns ------- dict Assignment submissions """ course = Course.get_by_id(course_id) assignments = course.get_assignments() assignment: Assignment = list( filter(lambda a: str(a.id) == assignment_id, assignments))[0] if assignment is None: return error("Could not find assignment"), 400 else: return response(data={"submissions": assignment.submissions})
def manage_courses(): """Returns a list of all courses in the school. Returns ------- dict All course data """ return response({"courses": Admin.get_courses()}), 200
def edit_assignment(course_id: str, assignment_id: str): """Edits assignment for the class Parameters ------- course_id: str The course ID to look up in the database assignment_id: str The assignment ID to look up in the database Returns ------- dict Edited assignment data """ course = Course.get_by_id(course_id) assignments = course.get_assignments() assignment: Assignment = list( filter(lambda a: str(a.id) == assignment_id, assignments))[0] if assignment is None: return error("Could not find assignment"), 400 try: file_list = get_existing_assignment_files() edited_assignment = Assignment( date_assigned=assignment.date_assigned, assigned_by=assignment.assigned_by, assigned_to=request.form["assigned_to"], due_by=request.form["due_by"], title=request.form["title"], content=request.form["content"], filenames=file_list, estimated_time=request.form["estimated_time"], # weight=request.form['weight'] ) edited_assignment.id = assignment.id course.edit_assignment(edited_assignment) # Assign to 'assignment' so form has new details assignment = edited_assignment except KeyError: return error("Not all fields satisfied"), 400 # Set default values for form. request.form["assigned_to"].default = assignment.assigned_to request.form["due_by"].default = assignment.due_by request.form["estimated_time"].default = assignment.estimated_time request.form["title"].default = assignment.title request.form["content"].default = assignment.content # request.form['weight'].default = assignment.weight request.files.default = assignment.filenames return response(data={"assignment": assignment.to_json()})
def submit(course_id: str, assignment_id: str): """Submit work for an assignment Parameters ---------- course_id : str The ID of the class for which the assignment was set assignment_id : str The ID of the assignment Returns ------- dict The view response """ assignment = db.courses.find_one( {"assignments._id": ObjectId(assignment_id)}, { "_id": 0, "assignments": { "$elemMatch": { "_id": ObjectId(assignment_id) } } }, )["assignments"][0] if assignment is not None and course_id in current_user.courses: try: file_list = [] files = request.files.getlist("files") if files[0].filename: for file_ in files: filename = file_.filename blob = upload_blob( uuid.uuid4().hex + "." + file_.content_type.split("/")[-1], file_, ) file_list.append((blob.name, filename)) submission = Submission( date_submitted=datetime.utcnow(), content=request.form["content"], filenames=file_list, student_id=current_user.id, assignment_id=assignment_id, ) current_user.add_submission(current_user.id, course_id, submission=submission) except KeyError: return error("Not all fields satisfied"), 400 else: logger.info(f"Submission {submission.id} made") return response(["Submission was a success"]), 200 else: return error("No assignment found"), 404
def assignments(): """Get all assignments for the signed in user Returns ------- dict The view response """ logger.info("Accessed all assignments") return response(data={"assignments": current_user.get_assignments()})
def add_student(): """Adds a student account to the system and sends an activation email. Returns ------- dict Flashes, student data from the form """ flashes = list() try: if not Student.get_by_email(request.form["email"]): student = Student( request.form["email"], request.form["first_name"], request.form["last_name"], ) student.password(request.form["password"]) except KeyError: return error("Not all fields satisfied"), 400 if student.add(): flashes.append("Student added!") logger.info(f"Student {student.email} added") token = current_user.get_activation_token() app = current_app._get_current_object() msg = Message( app.config["MAIL_SUBJECT_PREFIX"] + " " + "Account Activation Link", sender=app.config["MAIL_SENDER"], recipients=[student.email], ) msg.body = f"""Here is your account activation link: { url_for('student.activate_account', token=token, _external=True) } If you did not register for this account, you can ignore this email. If you need any further assistance, please contact [email protected]. """ mail.send(msg) return response(flashes), 200 else: logger.info(f"Error adding Student {student.email}") flashes.append("There was a problem adding this account"), 400 return response(flashes), 400
def student_search_info(): r"""This method is called when the user clicks on a result on the search bar Returns ------- dict Flashes, student data """ try: return response(None, Student.get_by_id(request.form["user_id"])), 200 except: return error("There was a problem finding this user"), 404
def logout(): """Logout the user Returns ------- dict The view response """ logger.info("LOGGED OUT: {} {} - ACCESS: {}".format( current_user.first_name, current_user.last_name, current_user._type)) logout_user() return response(["You have been logged out"]), 200
def add_student_to_parent(): r"""Adds a student to a parent. Returns ------- dict Flashes """ if Admin.add_student_to_parent(request.form["parent_id"], request.form["student_id"]): return response(["Added student to parent"]), 200 else: return error("There was an error adding this student"), 400
def add_teacher_to_course(): """Adds a teacher to a course. Returns ------- dict Flashes, teacher data from the form """ flashes = list() try: if Teacher.get_by_email(request.form["email"]): Admin.add_teacher( Course.get_by_department_number(request.form["number"])._id, request.form["email"], ) else: flashes.append("Account doesn't exist!") return response(flashes), 400 except KeyError: return response(flashes), 400
def remove_student_from_parent(): r"""Removes a student from a parent. Returns ------- dict Flashes """ if Admin.remove_student_from_parent(request.form["parent_id"], request.form["student_id"]): return response(["Removed student from parent"]), 200 else: return error("There was an error removing this student"), 400
def assignments_by_class(course_id: str): """Get assignments for a specific class Parameters ---------- course_id : str The ID of the class Returns ------- dict The view response """ course_assignments = Course.get_by_id(course_id).get_assignments() logger.info(f"All assignments from {course_id}.") return response(data={"assignments": course_assignments})
def mark_submission(course_id: str, assignment_id: str, submission_id: str): flashes = [] course = Course.get_by_id(course_id) assignments = course.get_assignments() assignment: Assignment = get(assignments, id=assignment_id) submission: Submission = get(assignment.submissions, id=submission_id) min_, max_ = course.grade_range if min_ < request.form["grade"] < max_: submission.update_grade(request.form["grade"]) flashes.append("Grade updated!") return response(flashes), 200 return error("Grade outside course grade boundary")
def get_course_info(course_id: str): """Gets all info for course. Returns ------- dict Flashes, all course info """ flashes = list() try: course_info = db.courses.find({"_id": ObjectId(course_id)}) except: return error("Unknown error while getting course info"), 400 return response(flashes, {"course_info": course_info}), 200
def get_names_by_search(): """Shows full names of people the user is searching Returns ------- dict Admin names """ try: admins = Admin.get_by_keyword(request.form["first_name"]) possible_admins = list() for admin in admins: admin_data = { "full_name": admin.first_name + " " + admin.last_name, } possible_admins.append(admin_data) return response(data={"possible_admins": possible_admins}), 200 except: return error("There are no admins by that name"), 404
def get_names_by_search(): """Shows full names of people the user is searching Returns ------- dict Teacher names """ try: teachers = Teacher.get_by_keyword(request.form["first_name"]) possible_teachers = list() for teacher in teachers: teacher_data = { "full_name": teacher.first_name + " " + teacher.last_name, } possible_teachers.append(teacher_data) return response(data={"possible_teachers": possible_teachers}), 200 except: return error("There are no teachers by that name"), 404
def get_names_by_search(): """Shows full names of people the user is searching Returns ------- dict Student names """ try: students = Student.get_by_keyword(request.form["first_name"]) possible_students = list() for student in students: student_data = { "full_name": student.first_name + " " + student.last_name, } possible_students.append(student_data) return response(data={"possible_students": possible_students}), 200 except: return error("There are no students by that name"), 404
def delete_calendar_events(): """Gets dictionary of calendar events for teacher Returns ------- dict The view response """ req_data = request.get_json() if req_data: title = req_data["title"] teacherDict = current_user.to_dict() teacher = Teacher.get_by_email(teacherDict["email"]) current_user.remove_calendar_event(teacher.id, title) events = current_user.get_calendar() return response(data={"events": events})
def assignment_by_id(course_id: str, assignment_id: str): """Get an assignment by its ID Parameters ---------- course_id : str The ID of the class assignment_id : str The ID of the assignment Returns ------- dict The view response """ assignments = current_user.get_assignments() assignment = get(assignments, id=assignment_id) logger.info( f"All assignments from {course_id} with assignment id {assignment_id}." ) return response(data={"assignment": assignment})
def view_assignment_by_class_id(course_id: str): """Collects assignments from a specific class Parameters ------- class_id: str The class ID to look up in the database Returns ------- dict The specified class and its respective data (id, name, and assignments) """ course_assignments = Course.get_by_id(course_id).get_assignments() return response( data={ "assignments": list(map(lambda a: a.to_dict(), course_assignments)) })
def request_password_reset(): """Request a password reset (while not authenticated) Returns ------- dict The view response """ if current_user.is_authenticated: return error( f"Wrong route, use {url_for('auth.change_password')}."), 303 try: email = request.form["email"].lower() send_reset_email(User.from_dict(User.get_by_email(email))) except KeyError: return error("Not all fields satisfied"), 400 else: return response(["An email has been sent to reset your password." ]), 200
def change_password(): """Changes the user password (while authenticated) Returns ------- dict The view response """ try: new_password = request.form["new_password"] current_user.password = new_password # TODO: I think this should definitely be update, not add, because add() can potentially add a new one if not current_user.add(): return error("Unknown error while changing the password."), 500 except KeyError: return error("Not all fields satisfied"), 400 else: return response(["Password changed"]), 200
def get_schedule_classes(): """Gets name, dates, and times for classes Returns ------- dict The view response """ student_course_ids = current_user.get_course_ids() class_schedule = list() for student_course in student_course_ids: data = Course.get_by_id(student_course) course_data = { "name": data.name, "daysOfWeek": data.schedule_days, "startTime": data.schedule_time, } class_schedule.append(course_data) return response(data={"class_schedule": class_schedule})