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)
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)
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')
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')
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"])
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'])
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'])
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')
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)
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}"
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}")
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"
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"
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"
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)
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"
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")
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": [] })
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"
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"] }})))
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)
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)
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"])
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"])
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"
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"
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}")
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)
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}"
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}")