From 12120eb62bc6a25cb88a2fdf551e8d81777cf5b0 Mon Sep 17 00:00:00 2001 From: Aron Buzogany <108480125+AronBuzogany@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:40:51 +0200 Subject: [PATCH] Added endpoint to add a user using a join code (#218) * Fix #71 * added course join endpoint * internal server error is 500 * fixed code docs --- .../endpoints/courses/courses_config.py | 3 + backend/project/endpoints/courses/join.py | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 backend/project/endpoints/courses/join.py diff --git a/backend/project/endpoints/courses/courses_config.py b/backend/project/endpoints/courses/courses_config.py index f791031f..03f1abca 100644 --- a/backend/project/endpoints/courses/courses_config.py +++ b/backend/project/endpoints/courses/courses_config.py @@ -15,6 +15,7 @@ from project.endpoints.courses.course_details import CourseByCourseId from project.endpoints.courses.course_admin_relation import CourseForAdmins from project.endpoints.courses.course_student_relation import CourseToAddStudents +from project.endpoints.courses.join import CourseJoin courses_bp = Blueprint("courses", __name__) courses_api = Api(courses_bp) @@ -30,3 +31,5 @@ courses_bp.add_url_rule("/courses//students", view_func=CourseToAddStudents.as_view('course_students')) + +courses_bp.add_url_rule("/courses/join", view_func=CourseJoin.as_view('course_join')) diff --git a/backend/project/endpoints/courses/join.py b/backend/project/endpoints/courses/join.py new file mode 100644 index 00000000..16ed002f --- /dev/null +++ b/backend/project/endpoints/courses/join.py @@ -0,0 +1,78 @@ +""" +This file contains the endpoint to join a course using a join code +""" + + +from os import getenv +from datetime import datetime +from zoneinfo import ZoneInfo + +from flask import request +from flask_restful import Resource + +from sqlalchemy.exc import SQLAlchemyError + +from project.models.course_share_code import CourseShareCode +from project.models.course_relation import CourseStudent, CourseAdmin + + +TIMEZONE = getenv("TIMEZONE", "GMT") +API_URL = getenv("API_HOST") + +class CourseJoin(Resource): + """ + Class that will respond to the /courses/join link + students or admins with a join code can join a course + """ + + def post(self, uid=None): # pylint: disable=too-many-return-statements + """ + Post function for /courses/join + students or admins with a join code can join a course + """ + + response = { + "url": f"{API_URL}/courses/join" + } + + data = request.get_json() + if not "join_code" in data: + return {"message": "join_code is required"}, 400 + + join_code = data["join_code"] + share_code = CourseShareCode.query.filter_by(join_code=join_code).first() + + if not share_code: + response["message"] = "Invalid join code" + return response, 400 + + if share_code.expiry_time and share_code.expiry_time < datetime.now(ZoneInfo(TIMEZONE)): + response["message"] = "Join code has expired" + return response, 400 + + + course_id = share_code.course_id + is_for_admins = share_code.for_admins + + course_relation = CourseStudent + if is_for_admins: + course_relation = CourseAdmin + + try: + relation = course_relation.query.filter_by(course_id=course_id, uid=uid).first() + if relation: + response["message"] = "User already in course" + return response, 400 + except SQLAlchemyError: + response["message"] = "Internal server error" + return response, 500 + + course_relation = course_relation(course_id=course_id, uid=uid) + + try: + course_relation.insert() + response["message"] = "User added to course" + return response, 201 + except SQLAlchemyError: + response["message"] = "Internal server error" + return response, 500