From deafa9a526227f698cb948e7b09c43ce308f40b3 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Sat, 25 Nov 2023 00:33:25 +0100 Subject: [PATCH] adding support to delete objects one at a time in the admin panel --- codeGrader/frontend/admin/app.py | 93 ++++++++++++++++++- .../frontend/admin/handlers/AdminUser.py | 47 +++++++++- .../frontend/admin/handlers/Exercise.py | 45 +++++++++ codeGrader/frontend/admin/handlers/Profile.py | 45 +++++++++ codeGrader/frontend/admin/handlers/Subject.py | 45 +++++++++ codeGrader/frontend/admin/handlers/Task.py | 65 +++++++++---- codeGrader/frontend/admin/handlers/User.py | 47 +++++++++- .../frontend/admin/handlers/__init__.py | 15 +-- .../frontend/admin/static/css/styling.css | 4 + .../frontend/admin/templates/adminUser.html | 3 + .../frontend/admin/templates/deleteAdmin.html | 24 +++++ .../admin/templates/deleteExercise.html | 24 +++++ .../admin/templates/deleteProfile.html | 24 +++++ .../admin/templates/deleteSubject.html | 24 +++++ .../frontend/admin/templates/deleteTask.html | 24 +++++ .../frontend/admin/templates/deleteUser.html | 24 +++++ .../frontend/admin/templates/exercise.html | 3 + .../frontend/admin/templates/profile.html | 3 + .../frontend/admin/templates/subject.html | 3 + codeGrader/frontend/admin/templates/task.html | 3 + codeGrader/frontend/admin/templates/user.html | 3 + codeGrader/frontend/util/api.py | 2 +- 22 files changed, 539 insertions(+), 31 deletions(-) create mode 100644 codeGrader/frontend/admin/templates/deleteAdmin.html create mode 100644 codeGrader/frontend/admin/templates/deleteExercise.html create mode 100644 codeGrader/frontend/admin/templates/deleteProfile.html create mode 100644 codeGrader/frontend/admin/templates/deleteSubject.html create mode 100644 codeGrader/frontend/admin/templates/deleteTask.html create mode 100644 codeGrader/frontend/admin/templates/deleteUser.html diff --git a/codeGrader/frontend/admin/app.py b/codeGrader/frontend/admin/app.py index 1d61b67..e453f5d 100644 --- a/codeGrader/frontend/admin/app.py +++ b/codeGrader/frontend/admin/app.py @@ -11,7 +11,8 @@ UserListHandler, UserHandler, HomeHandler, AdminListHandler, AdminHandler, ProfileListHandler, \ ProfileHandler, SubjectListHandler, SubjectHandler, TaskHandler, TaskListHandler, ExerciseHandler, \ ExerciseListHandler, AddAdminHandler, AddProfileHandler, AddUserHandler, AddTaskHandler, AddExerciseHandler, \ - AddSubjectHandler + AddSubjectHandler, DeleteUserHandler, DeleteSubjectHandler, DeleteAdminHandler, DeleteTaskHandler, \ + DeleteExerciseHandler, DeleteProfileHandler app = Flask(config.adminAppName, template_folder=templates.__path__[0]) @@ -121,6 +122,21 @@ def addUser(): return AddUserHandler(request).post() +@app.route("/user/delete/", methods=['GET', 'POST']) +@login_required +def deleteUser(id_: int): + """ + Deleting a user from the database + @param id_: The identifier of the user + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteUserHandler(request).get(id_) + elif request.method == 'POST': + return DeleteUserHandler(request).post(id_) + + @app.route("/admin/", methods=['GET', 'POST']) @login_required def admin(id_): @@ -158,6 +174,21 @@ def addAdmin(): return AddAdminHandler(request).post() +@app.route("/admin/delete/", methods=['GET', 'POST']) +@login_required +def deleteAdmin(id_: int): + """ + Deleting a Admin from the database + @param id_: The identifier of the Admin + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteAdminHandler(request).get(id_) + elif request.method == 'POST': + return DeleteAdminHandler(request).post(id_) + + @app.route("/profile/", methods=['GET', 'POST']) @login_required def profile(id_): @@ -196,6 +227,21 @@ def addProfile(): return AddProfileHandler(request).post() +@app.route("/profile/delete/", methods=['GET', 'POST']) +@login_required +def deleteProfile(id_: int): + """ + Deleting a profile from the database + @param id_: The identifier of the profile + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteProfileHandler(request).get(id_) + elif request.method == 'POST': + return DeleteProfileHandler(request).post(id_) + + @app.route("/subject/", methods=['GET', 'POST']) @login_required def subject(id_): @@ -234,6 +280,21 @@ def addSubject(): return AddSubjectHandler(request).post() +@app.route("/subject/delete/", methods=['GET', 'POST']) +@login_required +def deleteSubject(id_: int): + """ + Deleting a subject from the database + @param id_: The identifier of the subject + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteSubjectHandler(request).get(id_) + elif request.method == 'POST': + return DeleteSubjectHandler(request).post(id_) + + @app.route("/exercise/", methods=['GET', 'POST']) @login_required def exercise(id_): @@ -272,6 +333,21 @@ def addExercise(): return AddExerciseHandler(request).post() +@app.route("/exercise/delete/", methods=['GET', 'POST']) +@login_required +def deleteExercise(id_: int): + """ + Deleting a exercise from the database + @param id_: The identifier of the exercise + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteExerciseHandler(request).get(id_) + elif request.method == 'POST': + return DeleteExerciseHandler(request).post(id_) + + @app.route("/task/", methods=['GET', 'POST']) @login_required def task(id_): @@ -310,5 +386,20 @@ def addTask(): return AddTaskHandler(request).post() +@app.route("/task/delete/", methods=['GET', 'POST']) +@login_required +def deleteTask(id_: int): + """ + Deleting a exercise from the database + @param id_: The identifier of the exercise + @type id_: int + @return: Redirect to another view. + """ + if request.method == 'GET': + return DeleteTaskHandler(request).get(id_) + elif request.method == 'POST': + return DeleteTaskHandler(request).post(id_) + + if __name__ == "__main__": app.run(port=config.adminPort) diff --git a/codeGrader/frontend/admin/handlers/AdminUser.py b/codeGrader/frontend/admin/handlers/AdminUser.py index 3a852f7..25e9858 100644 --- a/codeGrader/frontend/admin/handlers/AdminUser.py +++ b/codeGrader/frontend/admin/handlers/AdminUser.py @@ -51,7 +51,7 @@ def get(self, id_: int): @return: The rendered page of the AdminUser @rtype: HTML """ - admin = self.api.get(f"/adminUser/{id_}") + admin = self.api.get(f"/admin/{id_}") admin_types = self.api.get(f"/adminTypes") admin["types"] = admin_types["admin_type"] @@ -140,3 +140,48 @@ def post(self): self.api.post(f"/admin/add", body=admin_data) return redirect(url_for("admins")) + + +class DeleteAdminHandler(BaseHandler): + """ + Handler to delete a Task from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteAdminHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of an Admin + @param id_: The id_ of the Admin + @type id_: int + @return: Rendered Template + """ + task = self.api.get(f"/admin/{id_}") + + return render_template("deleteAdmin.html", **task) + + def post(self, id_: int): + """ + Post Operation for Admin Deletion + Deletes the task in the backend via an API Call + @param id_: The idnentifier of the Admin + @type id_: int + @return: Redirection to the Admin table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/admin/{id_}") + + return redirect(url_for("admins")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("admin", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/Exercise.py b/codeGrader/frontend/admin/handlers/Exercise.py index 0c508f1..8cd72c7 100644 --- a/codeGrader/frontend/admin/handlers/Exercise.py +++ b/codeGrader/frontend/admin/handlers/Exercise.py @@ -104,3 +104,48 @@ def post(self): self.api.post("/exercise/add", body=exercise_data) return redirect(url_for("exercises")) + + +class DeleteExerciseHandler(BaseHandler): + """ + Handler to delete a Exercise from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteExerciseHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of a Exercise + @param id_: The id_ of the Exercise + @type id_: int + @return: Rendered Template + """ + task = self.api.get(f"/exercise/{id_}") + + return render_template("deleteExercise.html", **task) + + def post(self, id_: int): + """ + Post Operation for Exercise Deletion + Deletes the task in the backend via an API Call + @param id_: The idnentifier of the Exercise + @type id_: int + @return: Redirection to the Exercise table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/exercise/{id_}") + + return redirect(url_for("exercises")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("exercise", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/Profile.py b/codeGrader/frontend/admin/handlers/Profile.py index 7d6cb25..f30d6c9 100644 --- a/codeGrader/frontend/admin/handlers/Profile.py +++ b/codeGrader/frontend/admin/handlers/Profile.py @@ -104,3 +104,48 @@ def post(self): self.api.post("/profile/add", body=profile_data) return redirect(url_for("profiles")) + + +class DeleteProfileHandler(BaseHandler): + """ + Handler to delete a Profile from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteProfileHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of a Profile + @param id_: The id_ of the Profile + @type id_: int + @return: Rendered Template + """ + task = self.api.get(f"/profile/{id_}") + + return render_template("deleteProfile.html", **task) + + def post(self, id_: int): + """ + Post Operation for Profile Deletion + Deletes the task in the backend via an API Call + @param id_: The idnentifier of the Profile + @type id_: int + @return: Redirection to the Profile table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/profile/{id_}") + + return redirect(url_for("profiles")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("profile", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/Subject.py b/codeGrader/frontend/admin/handlers/Subject.py index f9e2e37..b4358cf 100644 --- a/codeGrader/frontend/admin/handlers/Subject.py +++ b/codeGrader/frontend/admin/handlers/Subject.py @@ -104,3 +104,48 @@ def post(self): self.api.post("/subject/add", body=subject_data) return redirect(url_for("subjects")) + + +class DeleteSubjectHandler(BaseHandler): + """ + Handler to delete a Subject from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteSubjectHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of a Subject + @param id_: The id_ of the Subject + @type id_: int + @return: Rendered Template + """ + subject = self.api.get(f"/subject/{id_}") + + return render_template("deleteSubject.html", **subject) + + def post(self, id_: int): + """ + Post Operation for Subject Deletion + Deletes the subject in the backend via an API Call + @param id_: The idnentifier of the Subject + @type id_: int + @return: Redirection to the Subject table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/subject/{id_}") + + return redirect(url_for("subjects")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("subject", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/Task.py b/codeGrader/frontend/admin/handlers/Task.py index 45e3720..cf8e22b 100644 --- a/codeGrader/frontend/admin/handlers/Task.py +++ b/codeGrader/frontend/admin/handlers/Task.py @@ -67,26 +67,6 @@ def post(self, id_: int): return redirect(url_for("task", id_=id_)) - def create(self): - """ - Create a User in the database - @return: - """ - user_data = dict() - - user_data["username"] = self.get_value("username") - user_data["first_name"] = self.get_value("first_name") - user_data["last_name"] = self.get_value("last_name") - user_data["email"] = self.get_value("email") - user_data["tag"] = self.get_value("tag") - user_data["profile"] = self.get_value("profile") - - response_text = self.api.post("/addUser", body=user_data) - - id_ = response_text["response"]["id"] - - return redirect(url_for("user", id_=id_)) - class AddTaskHandler(BaseHandler): """ @@ -124,3 +104,48 @@ def post(self): self.api.post("/task/add", body=task_data) return redirect(url_for("tasks")) + + +class DeleteTaskHandler(BaseHandler): + """ + Handler to delete a Task from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteTaskHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of a Task + @param id_: The id_ of the user + @type id_: int + @return: Rendered Template + """ + task = self.api.get(f"/task/{id_}") + + return render_template("deleteTask.html", **task) + + def post(self, id_: int): + """ + Post Operation for Task Deletion + Deletes the task in the backend via an API Call + @param id_: The idnentifier of the Task + @type id_: int + @return: Redirection to the Task table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/task/{id_}") + + return redirect(url_for("tasks")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("task", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/User.py b/codeGrader/frontend/admin/handlers/User.py index 2f2c848..bdaf776 100644 --- a/codeGrader/frontend/admin/handlers/User.py +++ b/codeGrader/frontend/admin/handlers/User.py @@ -88,7 +88,7 @@ class AddUserHandler(BaseHandler): def __init__(self, request: flask.Request): """ - Constructor of the AddAdminUser Handler + Constructor of the AddUser Handler @param request: The request from the app route of flask @type request: flask.Request """ @@ -128,3 +128,48 @@ def post(self): self.api.post(f"/user/add", body=user_data) return redirect(url_for("users")) + + +class DeleteUserHandler(BaseHandler): + """ + Handler to delete a user from the api backend + """ + + def __init__(self, request: flask.Request): + """ + Constructor of the DeleteuserHandler Handler + @param request: The request from the app route of flask + @type request: flask.Request + """ + super().__init__(request) + + def get(self, id_: int): + """ + Get Handler to render the site for confirmation for deletion of an user + @param id_: The id_ of the user + @type id_: int + @return: Rendered Template + """ + user = self.api.get(f"/user/{id_}") + + return render_template("deleteUser.html", **user) + + def post(self, id_: int): + """ + Post Operation for User Deletion + Deletes the user in the backend via an API Call + @param id_: The idnentifier of the user + @type id_: int + @return: Redirection to the users table + """ + if self.get_value("action_button") == "Submit": + response = self.api.delete(f"/user/{id_}") + + return redirect(url_for("users")) + + elif self.get_value("action_button") == "Cancel": + return redirect(url_for("user", id_=id_)) + + else: + pass + # TODO Implement Error diff --git a/codeGrader/frontend/admin/handlers/__init__.py b/codeGrader/frontend/admin/handlers/__init__.py index f902507..587a980 100644 --- a/codeGrader/frontend/admin/handlers/__init__.py +++ b/codeGrader/frontend/admin/handlers/__init__.py @@ -5,16 +5,17 @@ from .Login import AdminUserLoginHandler from .SessionAdmin import AdminSessionHandler, SessionAdmin -from .User import UserListHandler, UserHandler, AddUserHandler +from .User import UserListHandler, UserHandler, AddUserHandler, DeleteUserHandler from .Home import HomeHandler -from .AdminUser import AdminListHandler, AdminHandler, AddAdminHandler -from .Profile import ProfileHandler, ProfileListHandler, AddProfileHandler -from .Subject import SubjectHandler, SubjectListHandler, AddSubjectHandler -from .Task import TaskHandler, TaskListHandler, AddTaskHandler -from .Exercise import ExerciseHandler, ExerciseListHandler, AddExerciseHandler +from .AdminUser import AdminListHandler, AdminHandler, AddAdminHandler, DeleteAdminHandler +from .Profile import ProfileHandler, ProfileListHandler, AddProfileHandler, DeleteProfileHandler +from .Subject import SubjectHandler, SubjectListHandler, AddSubjectHandler, DeleteSubjectHandler +from .Task import TaskHandler, TaskListHandler, AddTaskHandler, DeleteTaskHandler +from .Exercise import ExerciseHandler, ExerciseListHandler, AddExerciseHandler, DeleteExerciseHandler __all__ = ["AdminUserLoginHandler", "AdminSessionHandler", "SessionAdmin", "UserListHandler", "UserHandler", "HomeHandler", "AdminHandler", "AdminListHandler", "ProfileListHandler", "ProfileHandler", "SubjectListHandler", "SubjectHandler", "ExerciseListHandler", "ExerciseHandler", "TaskHandler", "TaskListHandler", "AddAdminHandler", "AddProfileHandler", "AddExerciseHandler", "AddTaskHandler", - "AddSubjectHandler", "AddUserHandler"] + "AddSubjectHandler", "AddUserHandler", "DeleteUserHandler", "DeleteTaskHandler", "DeleteAdminHandler", + "DeleteProfileHandler", "DeleteExerciseHandler", "DeleteUserHandler", "DeleteSubjectHandler"] diff --git a/codeGrader/frontend/admin/static/css/styling.css b/codeGrader/frontend/admin/static/css/styling.css index 9f4f4ad..081aa7e 100644 --- a/codeGrader/frontend/admin/static/css/styling.css +++ b/codeGrader/frontend/admin/static/css/styling.css @@ -145,6 +145,10 @@ body { padding: 5px 10px; } +.btn_delete { + padding: 5px 10px; + background-color: red; +} .btn_login { margin: 10px; diff --git a/codeGrader/frontend/admin/templates/adminUser.html b/codeGrader/frontend/admin/templates/adminUser.html index 6ef8f6f..a387b6a 100644 --- a/codeGrader/frontend/admin/templates/adminUser.html +++ b/codeGrader/frontend/admin/templates/adminUser.html @@ -87,5 +87,8 @@

Admin User {{ username }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteAdmin.html b/codeGrader/frontend/admin/templates/deleteAdmin.html new file mode 100644 index 0000000..a75d988 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteAdmin.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete Admin {{ username }}

+
+

Admin {{ username }}

+
+ Are you sure you wanna delete Admin {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteExercise.html b/codeGrader/frontend/admin/templates/deleteExercise.html new file mode 100644 index 0000000..348b9a6 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteExercise.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete Exercise {{ username }}

+
+

Exercise {{ username }}

+
+ Are you sure you wanna delete Exercise {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteProfile.html b/codeGrader/frontend/admin/templates/deleteProfile.html new file mode 100644 index 0000000..b9c10c2 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteProfile.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete Profile {{ username }}

+
+

Profile {{ username }}

+
+ Are you sure you wanna delete Profile {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteSubject.html b/codeGrader/frontend/admin/templates/deleteSubject.html new file mode 100644 index 0000000..7c0c3a5 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteSubject.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete Subject {{ username }}

+
+

Subject {{ username }}

+
+ Are you sure you wanna delete Subject {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteTask.html b/codeGrader/frontend/admin/templates/deleteTask.html new file mode 100644 index 0000000..648b276 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteTask.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete Task {{ username }}

+
+

Task {{ username }}

+
+ Are you sure you wanna delete Task {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/deleteUser.html b/codeGrader/frontend/admin/templates/deleteUser.html new file mode 100644 index 0000000..b8b7e72 --- /dev/null +++ b/codeGrader/frontend/admin/templates/deleteUser.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block core %} +
+
+

Delete User {{ username }}

+
+

User {{ username }}

+
+ Are you sure you wanna delete User {{ username }}? +
+ +
+
+ + +
+
+ + + + +
+{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/exercise.html b/codeGrader/frontend/admin/templates/exercise.html index 4415601..211f2c2 100644 --- a/codeGrader/frontend/admin/templates/exercise.html +++ b/codeGrader/frontend/admin/templates/exercise.html @@ -29,5 +29,8 @@

Exercise {{ name }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/profile.html b/codeGrader/frontend/admin/templates/profile.html index a63949d..210968e 100644 --- a/codeGrader/frontend/admin/templates/profile.html +++ b/codeGrader/frontend/admin/templates/profile.html @@ -29,5 +29,8 @@

Profile {{ name }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/subject.html b/codeGrader/frontend/admin/templates/subject.html index b0f4dfd..582c6b6 100644 --- a/codeGrader/frontend/admin/templates/subject.html +++ b/codeGrader/frontend/admin/templates/subject.html @@ -29,5 +29,8 @@

Subject {{ name }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/task.html b/codeGrader/frontend/admin/templates/task.html index 9b49768..fab17de 100644 --- a/codeGrader/frontend/admin/templates/task.html +++ b/codeGrader/frontend/admin/templates/task.html @@ -29,5 +29,8 @@

Task {{ name }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/admin/templates/user.html b/codeGrader/frontend/admin/templates/user.html index 566503b..a6a128c 100644 --- a/codeGrader/frontend/admin/templates/user.html +++ b/codeGrader/frontend/admin/templates/user.html @@ -70,5 +70,8 @@

User {{ username }}

+
+ +
{% endblock core %} diff --git a/codeGrader/frontend/util/api.py b/codeGrader/frontend/util/api.py index d75247c..44cb128 100644 --- a/codeGrader/frontend/util/api.py +++ b/codeGrader/frontend/util/api.py @@ -135,7 +135,7 @@ def delete(self, path: str): """ response = self._make_request('DELETE', path) - assert response.status_code == 200 + assert response.status_code == 200 or response.status_code == 204 assert response.text is not None return self._cast_dict(response.text)