Esempio n. 1
0
    def test_get_all(self):
        rv = self.app.get('/feeds')

        self.assertEqual(rv.status_code, 200)

        util.verify_headers(rv)

        store.get_feeds.assert_called_with(is_public=True)
Esempio n. 2
0
    def test_get_single_not_found(self):
        rv = self.app.get('/feeds/bar')

        self.assertEqual(rv.status_code, 404)

        util.verify_headers(rv)

        store.get_feeds.assert_called_with(is_public=True)
Esempio n. 3
0
    def test_get_single(self):
        rv = self.app.get('/feeds/foo')

        self.assertEqual(rv.status_code, 200)

        util.verify_headers(rv)

        store.get_feeds.assert_called_with(is_public=True)

        self._feed.dict.assert_called_with(admin=None, base_uri='base_uri')
Esempio n. 4
0
    def test_get_all_admin_unauthorized(self):
        rv = self.app.get('/feeds?admin=true')

        self.assertEqual(rv.status_code, 200)

        util.verify_headers(rv)

        store.get_feeds.assert_called_with(is_public=True)

        self._feed.dict.assert_called_with(admin=None, base_uri='base_uri')
Esempio n. 5
0
    def test_get(self):
        rv = self.app.get('/token')

        self.assertEqual(rv.status_code, 200)

        util.verify_headers(rv)

        resp_data = json.loads(rv.data.decode('utf-8'))

        self.assertIn("data", resp_data)
        self.assertIn("token", resp_data["data"])
Esempio n. 6
0
    def test_not_found_with_close_match(self):
        rv = self.app.post('/fee')

        self.assertEqual(rv.status_code, 404)

        util.verify_headers(rv)

        resp_data = json.loads(rv.data.decode('utf-8'))

        self.assertIn("meta", resp_data)
        self.assertIn("code", resp_data['meta'])
        self.assertIn("error_type", resp_data['meta'])
        self.assertIn("error_message", resp_data['meta'])
Esempio n. 7
0
    def test_invalid_method(self):
        rv = self.app.post('/feeds')

        self.assertEqual(rv.status_code, 405)

        util.verify_headers(rv)

        resp_data = json.loads(rv.data.decode('utf-8'))

        self.assertIn("meta", resp_data)
        self.assertIn("code", resp_data['meta'])
        self.assertIn("error_type", resp_data['meta'])
        self.assertIn("error_message", resp_data['meta'])
Esempio n. 8
0
    def test_get_single_admin_authorized(self):
        # get an auth token
        token_rv = self.app.get('/token')

        token = json.loads(token_rv.data.decode('utf-8'))['data']['token']

        rv = self.app.get('/feeds/foo?admin=true&access_token=' + token)

        self.assertEqual(rv.status_code, 200)

        util.verify_headers(rv)

        store.get_feeds.assert_called_with(is_public=None)

        self._feed.dict.assert_called_with(admin=True, base_uri='base_uri')
Esempio n. 9
0
def deleteclassroom():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id

    class_id = request.form.get("class_id", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id != classroom["owner_id"]:
        return abort(404)

    user_db.update_many({"id": {
        "$in": classroom["students"]
    }}, {"$pull": {
        "classrooms": int(class_id)
    }})
    user_db.update_many({"id": {
        "$in": classroom["teachers"]
    }}, {"$pull": {
        "classrooms": int(class_id)
    }})

    assignment_db.delete_many({"id": {"$in": classroom["assignments"]}})

    if classroom["studentInviteLink"] != None:
        invitelinks_db.delete_one({"link": classroom["studentInviteLink"]})
        invitecodes_db.delete_one({"code": classroom["studentInviteCode"]})
    if classroom["teacherInviteLink"] != None:
        invitelinks_db.delete_one({"link": classroom["teacherInviteLink"]})
        invitecodes_db.delete_one({"code": classroom["teacherInviteCode"]})

    classroom_db.delete_one({"id": int(class_id)})

    return redirect(base_url)
Esempio n. 10
0
def editassignment():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)
    assignment_id = request.form.get("assignmentId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"] or int(
            assignment_id) not in classroom["assignments"]:
        return abort(404)

    name = request.form.get("name", None)
    instructions = request.form.get("instructions", None)

    if not name or len(name.replace(" ", "")) == 0:
        return "Invalid Name"
    if not instructions or len(instructions.replace(" ", "")) == 0:
        return "Invalid Instructions"

    assignment_db.update_one(
        {"id": int(assignment_id)},
        {"$set": {
            "name": name,
            "instructions": instructions
        }})

    return f"/classroom/{class_id}/{assignment_id}"
Esempio n. 11
0
def sendfeedback():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id

    class_id = request.form.get("class_id", None)
    student_id = request.form.get("student_id", None)
    assignment_id = request.form.get("assignment_id", None)
    feedback = request.form.get("feedback", None)

    classroom = classroom_db.find_one({"id": int(class_id)})
    assignment = assignment_db.find_one({"id": int(assignment_id)})

    if classroom == None or int(
            student_id) not in classroom["students"] or int(
                assignment_id) not in classroom["assignments"] or assignment[
                    "submissions"][str(student_id)]["status"] not in [
                        "awaiting feedback", "returned"
                    ]:
        return abort(404)

    if user_id not in classroom["teachers"]:
        return abort(404)

    submissions = assignment["submissions"]
    submissions[str(student_id)]["feedback"] = feedback
    submissions[str(student_id)]["status"] = "returned"
    assignment_db.update_one({"id": int(assignment_id)},
                             {"$set": {
                                 "submissions": submissions
                             }})

    return redirect(f"{base_url}/classroom/{class_id}/{assignment_id}")
Esempio n. 12
0
def inviteteacher():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)

    teacher = asyncio.run(client.get_user(request.form.get("username", "")))

    if str(teacher) == "None":
        return "User not found"

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"]:
        return abort(404)

    teacher_id = teacher.id
    db_teacher = user_db.find_one({"id": teacher_id})

    if db_teacher == None:
        teacher = {
            "id": teacher_id,
            "username": teacher.name,
            "pfp": teacher.avatar,
            "first_name": teacher.first_name,
            "last_name": teacher.last_name,
            "roles": util.parse_roles(teacher.roles),
            "classrooms": [],
            "classroomInvites": []
        }
        user_db.insert_one(teacher)
    else:
        teacher = db_teacher

    if user_id == teacher_id:
        return "You can't invite yourself"

    if int(class_id) in [i["class_id"] for i in teacher["classroomInvites"]]:
        return "User has already been invited"

    if teacher_id in classroom["students"]:
        return "User is already a student in this classroom"

    if teacher_id in classroom["teachers"]:
        return "User is already a teacher in this classroom"

    owner = user_db.find_one({"id": classroom["owner_id"]})

    user_db.update_one({"id": teacher_id}, {
        "$push": {
            "classroomInvites": {
                "class_id": int(class_id),
                "type": "teacher",
                "class_name": classroom["name"],
                "owner_username": owner["username"],
                "owner_pfp": owner["pfp"]
            }
        }
    })

    return "User has been invited"
Esempio n. 13
0
def removestudent():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id

    class_id = request.form.get("class_id", None)
    student_id = request.form.get("student_id", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or int(student_id) not in classroom[
            "students"] or user_id not in classroom["teachers"]:
        return abort(404)

    classroom_db.update_one({"id": int(class_id)},
                            {"$pull": {
                                "students": int(student_id)
                            }})
    user_db.update_one({"id": int(student_id)},
                       {"$pull": {
                           "classrooms": int(class_id)
                       }})

    for assignment_id in classroom["assignments"]:
        assignment = assignment_db.find_one({"id": assignment_id})
        del assignment["submissions"][student_id]
        assignment_db.update_one(
            {"id": assignment_id},
            {"$set": {
                "submissions": assignment["submissions"]
            }})

    return "Success"
Esempio n. 14
0
def decline():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)
    inviteType = request.form.get("type", None)

    if not inviteType:
        return abort(404)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id in classroom[inviteType + "s"]:
        return abort(404)

    user = user_db.find_one({"id": user_id})

    if int(class_id) in user["classroomInvites"]:
        newInvites = []
        for i in user["classroomInvites"]:
            if i["class_id"] != int(class_id):
                newInvites.append(i)
        user_db.update_one({"id": user_id},
                           {"$set": {
                               "classroomInvites": newInvites
                           }})
    else:
        return abort(404)

    return "Success"
Esempio n. 15
0
    def verify_response(self, resp, code=200, pagination=None, data=None):
        util.verify_headers(resp)

        self.assertEqual(resp.status_code, code, resp.data)

        resp_data = json.loads(resp.data.decode('utf-8'))

        # meta is always expected
        self.assertIn("meta", resp_data)
        self.assertIn("code", resp_data["meta"])
        self.assertEqual(code, resp_data["meta"]["code"])

        if resp.status_code / 200 != 1:
            self.assertIn("error_type", resp_data["meta"])
            self.assertIn("error_message", resp_data["meta"])

        # extra checks around BadRequest response
        if resp.status_code == 400:
            self.assertEqual(resp_data["meta"]["error_type"], "BadRequest")
            self.assertIn("Invalid", resp_data["meta"]["error_message"])

        # data always expected
        self.assertIn("data", resp_data)

        if data is not None:
            self.assertEqual(data, resp_data["data"])

        if pagination is not None:
            self.assertIn("pagination", resp_data)

            expected_next = pagination.get("next")

            if expected_next is not None:
                self.assertIn("next", resp_data["pagination"])

                self.assertEqual(
                    urllib.parse.parse_qs(
                        urllib.parse.urlparse(expected_next).query
                    ),
                    urllib.parse.parse_qs(
                        urllib.parse.urlparse(
                            resp_data["pagination"]["next"]
                        ).query
                    )
                )
        else:
            self.assertNotIn("pagination", resp_data)
Esempio n. 16
0
def accept():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)
    inviteType = request.form.get("type", None)

    if not inviteType:
        return abort(404)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id in classroom[inviteType + "s"]:
        return abort(404)

    user = user_db.find_one({"id": user_id})

    if int(class_id) in [i["class_id"] for i in user["classroomInvites"]]:
        newInvites = []
        for i in user["classroomInvites"]:
            if i["class_id"] != int(class_id):
                newInvites.append(i)
        user_db.update_one({"id": user_id},
                           {"$set": {
                               "classroomInvites": newInvites
                           }})
    else:
        return abort(404)

    classroom_db.update_one({"id": int(class_id)},
                            {"$push": {
                                f"{inviteType}s": user_id
                            }})
    user_db.update_one({"id": user_id},
                       {"$push": {
                           "classrooms": int(class_id)
                       }})

    if inviteType == "student":
        for assignment in assignment_db.find(
            {"id": {
                "$in": classroom["assignments"]
            }}):
            submissions = assignment["submissions"]
            submissions[str(user_id)] = {
                "status": "not viewed",
                "repl_url": None,
                "feedback": None
            }
            assignment_db.update_one({"id": assignment["id"]},
                                     {"$set": {
                                         "submissions": submissions
                                     }})

    return "Success"
Esempio n. 17
0
def getmakeassignmentsform():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"]:
        return abort(404)

    return render_template("create_assignment.html", type="make")
Esempio n. 18
0
def before_request():
    if "/static/" not in request.path:
        if not util.verify_headers(request.headers):
            return render_template("login.html")

    user = util.verify_headers(request.headers)
    if user:
        user = asyncio.run(client.get_user(user))
        user_id = user.id
        if user_db.find_one({"id": user_id}) == None:
            user_db.insert_one({
                "id": user_id,
                "username": user.name,
                "pfp": user.avatar,
                "first_name": user.first_name,
                "last_name": user.last_name,
                "roles": util.parse_roles(user.roles),
                "classrooms": [],
                "classroomInvites": []
            })
Esempio n. 19
0
def edit_class():
    form = request.form
    files = request.files
    user = util.verify_headers(request.headers)

    name = form.get("name", None)
    classroom_id = form.get("classId", None)
    description = form.get("description", None)
    classroom_pfp = files.get("classroom-pfp", None)
    try:
        Image.open(classroom_pfp)
    except:
        classroom_pfp = None

    user = (asyncio.run(client.get_user(user)))
    user_id = user.id

    classroom = classroom_db.find_one({"id": int(classroom_id)})

    if len(name.replace(" ", "")) == 0 or not name:
        return "Invalid Name"
    if classroom == None or user_id not in classroom["teachers"]:
        return abort(404)
    if classroom_pfp != None and not util.allowed_file(classroom_pfp.filename):
        return "Invalid File Type"
    if len(description.replace(" ", "")) == 0:
        description = "A " + util.langs[
            classroom["language"]]["name"] + " classroom"

    if not classroom_pfp:
        cloud_img_url = classroom["classroom_pfp_url"]
    else:
        filename = classroom_id + "." + classroom_pfp.filename.split(".")[1]
        Image.open(classroom_pfp).convert("RGB").save(filename)
        r = cloudinary.uploader.upload(filename,
                                       folder="classrooms/",
                                       public_id=classroom_id,
                                       overwrite=True,
                                       resource_type="image")
        cloud_img_url = r["url"].replace("http://", "https://")
        os.remove(filename)

    classroom_db.update_one({"id": int(classroom_id)}, {
        "$set": {
            "name": name,
            "description": description,
            "classroom_pfp_url": cloud_img_url
        }
    })

    return f"/classroom/{classroom_id}/teachers"
Esempio n. 20
0
def landing():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user = user_db.find_one({"id": user.id})

    return render_template("landing.html",
                           langs=util.langs,
                           users=user_db.find(),
                           allClassrooms=list(classroom_db.find()),
                           invites=user["classroomInvites"],
                           userClassrooms=list(
                               classroom_db.find(
                                   {"id": {
                                       "$in": user["classrooms"]
                                   }})))
Esempio n. 21
0
def get_classroom(id):
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    id = int(id)
    user_id = user.id

    classroom = classroom_db.find_one({"id": id})
    assignments = assignment_db.find({"id": {"$in": classroom["assignments"]}})

    if id in user_db.find_one({"id": user_id})["classrooms"]:
        return render_template("classroom.html",
                               userId=user_id,
                               classroomId=id,
                               assignments=list(assignments),
                               classroom=classroom,
                               teacher=user_id in classroom["teachers"])
    return abort(404)
Esempio n. 22
0
def getaddteachersform():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if not class_id: return abort(404)
    if classroom == None: return abort(404)
    if user_id not in classroom["teachers"]: return abort(404)

    if not classroom["teacherInviteLink"]:
        inviteLink = util.randomstr(15)
        while invitelinks_db.find_one({"link": inviteLink}):
            inviteLink = util.randomstr(15)
        classroom_db.update_one({"id": int(class_id)},
                                {"$set": {
                                    "teacherInviteLink": inviteLink
                                }})
        invitelinks_db.insert_one({
            "link": inviteLink,
            "classroom": int(class_id),
            "type": "teacher"
        })
    else:
        inviteLink = classroom["teacherInviteLink"]

    if not classroom["teacherInviteCode"]:
        inviteCode = util.randomstr(10)
        while invitecodes_db.find_one({"code": inviteCode}):
            inviteCode = util.randomstr(10)
        classroom_db.update_one({"id": int(class_id)},
                                {"$set": {
                                    "teacherInviteCode": inviteCode
                                }})
        invitecodes_db.insert_one({
            "code": inviteCode,
            "classroom": int(class_id),
            "type": "teacher"
        })
    else:
        inviteCode = classroom["teacherInviteCode"]

    return render_template("add_people.html",
                           type="teacher",
                           inviteLink=inviteLink,
                           inviteCode=inviteCode)
Esempio n. 23
0
def cloneform():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"]:
        return abort(404)

    return render_template("create_class.html",
                           type="clone",
                           langs=util.langs,
                           name=classroom["name"],
                           language=classroom["language"],
                           description=classroom["description"],
                           pfp_url=classroom["classroom_pfp_url"])
Esempio n. 24
0
def geteditassignmentsform():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)
    assignment_id = request.form.get("assignmentId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"] or int(
            assignment_id) not in classroom["assignments"]:
        return abort(404)

    assignment = assignment_db.find_one({"id": int(assignment_id)})

    return render_template("create_assignment.html",
                           type="edit",
                           name=assignment["name"],
                           instructions=assignment["instructions"])
Esempio n. 25
0
def join():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id

    inviteCode = request.form.get("invite_code", "None").upper()

    code_doc = invitecodes_db.find_one({"code": inviteCode})

    if code_doc != None:
        class_id = code_doc["classroom"]
        classroom = classroom_db.find_one({"id": class_id})
        type = code_doc["type"]
        if user_id not in classroom["teachers"] and user_id not in classroom[
                "students"]:
            classroom_db.update_one({"id": class_id},
                                    {"$addToSet": {
                                        f"{type}s": user_id
                                    }})
            user_db.update_one({"id": user_id},
                               {"$addToSet": {
                                   "classrooms": class_id
                               }})
            if type == "student":
                for assignment in assignment_db.find(
                    {"id": {
                        "$in": classroom["assignments"]
                    }}):
                    submissions = assignment["submissions"]
                    submissions[str(user_id)] = {
                        "status": "not viewed",
                        "repl_url": None,
                        "feedback": None
                    }
                    assignment_db.update_one(
                        {"id": assignment["id"]},
                        {"$set": {
                            "submissions": submissions
                        }})
            ext = ""
            if type == "teacher": ext = "/teachers"
            return f"{base_url}/classroom/{class_id}{ext}"
        return "You are already in this classroom"

    return "Invalid Code"
Esempio n. 26
0
def setrepl():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    repl_url = request.form.get("repl_url", None)
    class_id = request.form.get("class_id", None)
    assignment_id = request.form.get("assignment_id", None)

    classroom = classroom_db.find_one({"id": int(class_id)})
    assignment = assignment_db.find_one({"id": int(assignment_id)})

    if classroom == None or int(assignment_id) not in classroom[
            "assignments"] or user_id not in classroom[
                "students"] or assignment["submissions"][str(
                    user_id)]["repl_url"] != None:
        return "Invalid"

    if not repl_url:
        return "No repl provided"

    if repl_url.lower().startswith("http://"):
        repl_url = "https://" + repl_url[7:]

    user = user_db.find_one({"id": user_id})

    if (not repl_url.lower().startswith("https://repl.it/@" +
                                        user["username"].lower() + "/") and
            not repl_url.lower().startswith("https://replit.com/@" +
                                            user["username"].lower() + "/")):
        return "Invalid repl url"

    if len(repl_url.lower()[8:].split("/")) != 3:
        return "Invalid repl url"

    repl_url = repl_url.split("#")[0]

    submissions = assignment["submissions"]
    submissions[str(user_id)]["repl_url"] = repl_url
    submissions[str(user_id)]["status"] = "in progress"
    assignment_db.update_one({"id": int(assignment_id)},
                             {"$set": {
                                 "submissions": submissions
                             }})

    return "Success"
Esempio n. 27
0
def deleteassignment():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("class_id", None)
    assignment_id = request.form.get("assignment_id", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"] or int(
            assignment_id) not in classroom["assignments"]:
        return abort(404)

    classroom_db.update_one({"id": int(class_id)},
                            {"$pull": {
                                "assignments": int(assignment_id)
                            }})
    assignment_db.delete_one({"id": int(assignment_id)})

    return redirect(f"{base_url}/classroom/{class_id}")
Esempio n. 28
0
def invite(inviteLink):
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id

    inviteLink = inviteLink.upper()

    link_doc = invitelinks_db.find_one(({"link": inviteLink}))

    if link_doc != None:
        class_id = link_doc["classroom"]
        classroom = classroom_db.find_one({"id": class_id})
        type = link_doc["type"]
        if user_id not in classroom["teachers"] and user_id not in classroom[
                "students"]:
            classroom_db.update_one({"id": class_id},
                                    {"$addToSet": {
                                        f"{type}s": user_id
                                    }})
            if type == "student":
                for assignment in assignment_db.find(
                    {"id": {
                        "$in": classroom["assignments"]
                    }}):
                    submissions = assignment["submissions"]
                    submissions[str(user_id)] = {
                        "status": "not viewed",
                        "repl_url": None,
                        "feedback": None
                    }
                    assignment_db.update_one(
                        {"id": assignment["id"]},
                        {"$set": {
                            "submissions": submissions
                        }})
        ext = ""
        if type == "teacher": ext = "/teachers"
        return redirect(f"{base_url}/classroom/{class_id}{ext}")

    return abort(404)
Esempio n. 29
0
def makeassignment():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("classId", None)

    classroom = classroom_db.find_one({"id": int(class_id)})

    if classroom == None or user_id not in classroom["teachers"]:
        return abort(404)

    name = request.form.get("name", None)
    instructions = request.form.get("instructions", None)

    if not name or len(name.replace(" ", "")) == 0:
        return "Invalid Name"
    if not instructions or len(instructions.replace(" ", "")) == 0:
        return "Invalid Instructions"

    submissions = {}
    for student_id in classroom["students"]:
        submissions[str(student_id)] = {
            "status": "not viewed",
            "repl_url": None,
            "feedback": None
        }
    assignment_id = util.next_id(assignment_db.find())
    assignment_db.insert_one({
        "id": assignment_id,
        "name": name,
        "instructions": instructions,
        "modal_answer_url": None,
        "submissions": submissions
    })
    classroom_db.update_one({"id": int(class_id)},
                            {"$push": {
                                "assignments": assignment_id
                            }})

    return f"/classroom/{class_id}/{assignment_id}"
Esempio n. 30
0
def submit():
    user = asyncio.run(client.get_user(util.verify_headers(request.headers)))
    user_id = user.id
    class_id = request.form.get("class_id", None)
    assignment_id = request.form.get("assignment_id", None)

    classroom = classroom_db.find_one({"id": int(class_id)})
    assignment = assignment_db.find_one({"id": int(assignment_id)})

    if classroom == None or user_id not in classroom["students"] or int(
            assignment_id) not in classroom["assignments"] or assignment[
                "submissions"][str(user_id)]["status"] != "in progress":
        return abort(404)

    submissions = assignment["submissions"]
    submissions[str(user_id)]["status"] = "awaiting feedback"
    assignment_db.update_one({"id": int(assignment_id)},
                             {"$set": {
                                 "submissions": submissions
                             }})

    return redirect(f"{base_url}/classroom/{class_id}")