def updatePassword(): # Takes in a json of the form {email : '', password : ''} # Validate that the user calling this has access # Either that they are the same user or that they are an admin if request.json is None: abort(400) for x in ['email', 'password']: if x not in request.json: abort(400) emailSess = mailsane.normalize(session['email']) if emailSess.error: abort(400) email = mailsane.normalize(request.json['email']) if email.error: abort(400) if dbworker.validateAccess(dbworker.userTypeMap['admin']): pass else: abort(401) if dbworker.getUser(str(email)) is None: abort(404) dbworker.setPassword(str(email), request.json['password']) return jsonify({'success': True})
def removeStudent(): """ Takes in a JSON of the structure {'email', 'classId'} Removes <email> from <classId> as a student Returns {'success' : Boolean} """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None or 'email' not in request.json or 'classId' not in request.json: abort(400) email = mailsane.normalize(request.json['email']) if email.error: abort(400) convClassId = ObjectId(request.json['classId']) try: validate(instance=request.json, schema=SchemaFactory.move_user) except exceptions.ValidationError: abort(400) us = dbworker.getUser(str(email)) cl = dbworker.getClass(convClassId) if us is None or cl is None: abort(404) if us['userType'] not in [dbworker.userTypeMap['student']]: abort(400) return jsonify( {'success': dbworker.removeStudent(convClassId, str(email))})
def deleteMarkingSection(): """ Takes in a JSON of the following format {classId, sectionTitle} Returns {success : Boolean} Deletes mark weights and marks for sectionTitle in <classId> """ # Validate credentials here if 'email' not in session or session['email'] is None: abort(401) email = mailsane.normalize(session['email']) if email.error: abort(400) if request.json is None: abort(400) for x in ['classId', 'sectionTitle']: if x not in request.json: abort(400) convClassId = ObjectId(request.json['classId']) if not dbworker.validateAccess( dbworker.userTypeMap['admin']) and not dbworker.isClassInstructor( str(email), convClassId): abort(401) dbworker.deleteMarkingSection(convClassId, request.json['sectionTitle']) return jsonify({'success': True})
def getMyMarks(): """ Gets a student's marks If the logged in user is not a student, then it will return a 403 Returned structure is {marks : {}, success : Boolean} The keys for marks and markingSections will be class _ids """ if not dbworker.validateAccess(dbworker.userTypeMap['student']): abort(403) email = mailsane.normalize(session['email']) if email.error: abort(400) marks = dbworker.getReports({'studentEmail': str(email)}) classList = [] marksDict = {} for m in marks: # This is to hide the internal report _ids m.pop('_id', None) tmpId = m['classId'] m.pop('classId', None) # This has to be done as ObjectIds not serializable m.pop('studentEmail', None) classList.append(tmpId) marksDict[str(tmpId)] = m markingSections = dbworker.getMarkingSectionInformation( filt={'_id': { '$in': classList }}) for cl in classList: stredCl = str(cl) tmp = {} for sectionTitle in markingSections[stredCl]: tmp[sectionTitle] = {} tmp[sectionTitle]['weight'] = markingSections[stredCl][ sectionTitle]['weight'] tmp[sectionTitle]['index'] = markingSections[stredCl][ sectionTitle]['index'] if sectionTitle in marksDict[stredCl]['marks']: # This is to handle the case where a 'None' mark exists tmp[sectionTitle]['mark'] = marksDict[stredCl]['marks'][ sectionTitle] else: tmp[sectionTitle]['mark'] = None marksDict[stredCl]['marks'] = tmp return jsonify({'marks': marksDict, 'success': True})
def getAllClasses(): """ Returns a list of class ids from the database """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(401) return jsonify({'classList': dbworker.getAllClasses()})
def createUser(): """ Takes in a JSON of the structure { "email": "*****@*****.**", "password": "******", "userType": 1, "firstName": "Test", "lastName": "Admin", "phoneNumber": "555-555-5555", "birthday": "YYYY-MM-DD", "parentEmail" : "", "parentName" : "" } Returns {'success' : Boolean} """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None: abort(400) for x in [ 'email', 'password', 'userType', 'firstName', 'lastName', 'phoneNumber', 'birthday', 'parentEmail', 'parentName' ]: if x not in request.json: abort(400) email = mailsane.normalize(request.json['email']) if email.error: abort(400) # Verify no duplicate email here or in the dbworker method # likely better to do it there parentEmail = mailsane.normalize(request.json['parentEmail']) if parentEmail.error: abort(400) try: validate(instance=request.json, schema=SchemaFactory.create_user) except exceptions.ValidationError: abort(400) if dbworker.getUser(str(email)) is not None: abort(400) dbworker.createUser( str(email), str(parentEmail), request.json['firstName'], request.json['lastName'], request.json['password'], request.json['userType'], request.json['phoneNumber'], datetime.datetime.strptime(request.json['birthday'], '%Y-%m-%d'), request.json['parentName']) return jsonify({'success': True})
def editHours(): """ Takes in a json of the form {'currentId' : id of hour log as string, 'newAttributes' : {...}} It can change any attribute that is not the _id """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None or 'currentId' not in request.json or 'newAttributes' not in request.json: abort(400) convClassId = ObjectId(request.json['currentId']) # Validate that all the changes made are valid # ie. ban changes to any invalid attributes if request.json['newAttributes'] == {} or '_id' in request.json[ 'newAttributes']: # No changes requested or an attempt was made to change the _id abort(400) try: validate(instance=request.json, schema=SchemaFactory.edit_hours) except exceptions.ValidationError: abort(400) if 'dateTime' in request.json['newAttributes']: # Convert dateTime from string to datetime object # See https://stackoverflow.com/questions/969285/how-do-i-translate-an-iso-8601-datetime-string-into-a-python-datetime-object correctedTime = None try: correctedTime = datetime.datetime.strptime( request.json['newAttributes']['dateTime'], "%Y-%m-%dT%H:%M:%S.%fZ") except: abort(400) correctedDict = {} for x in request.json['newAttributes']: if x == 'dateTime': correctedDict['dateTime'] = correctedTime else: correctedDict[x] = request.json['newAttributes'][x] dbworker.editHour(convClassId, correctedDict) else: dbworker.editHour(convClassId, request.json['newAttributes']) return jsonify({'success': True})
def handleSpreadSheet(): if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.files is None or 'file' not in request.files: abort(400) sheetFile = request.files['file'] try: sheetHandler = spreadSheetHandler.SheetHandler(sheetFile) failures = sheetHandler.assignSpreadSheetUsers() return jsonify(failures) except XLRDError as e: abort(400)
def updateCourseInfo(): """ Takes in a JSON of the following format {classId, status : Boolean, newTitle : String} Returns {success : Boolean} Sets the <ongoing> of classId to <status>, and <courseTitle> to <newTitle> If <semesterInfo> is in request.json, it will update <semester> to <semesterInfo> """ # Validate credentials here if 'email' not in session or session['email'] is None: abort(403) email = mailsane.normalize(session['email']) if email.error: abort(400) if request.json is None or 'classId' not in request.json or 'status' not in request.json or 'newTitle' not in request.json: abort(400) convClassId = ObjectId(request.json['classId']) if not dbworker.validateAccess( dbworker.userTypeMap['admin']) and not dbworker.isClassInstructor( str(email), convClassId): abort(401) try: validate(instance=request.json, schema=SchemaFactory.update_CI) except exceptions.ValidationError: abort(400) json = { 'ongoing': request.json['status'], 'courseTitle': request.json['newTitle'] } if 'semesterInfo' in request.json: json['semester'] = request.json['semesterInfo'] dbworker.updateClassInfo(convClassId, json) return jsonify({'success': True})
def setMarkingSection(): """ Takes in a JSON of the following format {classId, sectionTitle, weightInfo : JSON} weightInfo will be of the form {'weight' : Int, 'index' : Int} Returns {success : Boolean} Sets the weight of sectionTitle in classId to <weight> This will override existing values """ if request.json is None or 'classId' not in request.json or 'sectionTitle' not in request.json or 'weightInfo' not in request.json: abort(400) for x in ['weight', 'index']: if x not in request.json['weightInfo']: abort(400) # Validate credentials here if 'email' not in session or session['email'] is None: abort(401) email = mailsane.normalize(session['email']) if email.error: abort(400) try: validate(instance=request.json, schema=SchemaFactory.set_marking) except exceptions.ValidationError: abort(400) convClassId = ObjectId(request.json['classId']) if not dbworker.validateAccess( dbworker.userTypeMap['admin']) and not dbworker.isClassInstructor( str(email), convClassId): abort(401) dbworker.addMarkingSection(convClassId, request.json['sectionTitle'], request.json['weightInfo']) return jsonify({'success': True})
def createCourse(): """ Takes in a JSON of {'courseTitle'} Returns {'_id' : newId (String), 'success' : True} """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None or 'courseTitle' not in request.json: abort(400) semester = "" if 'semester' in request.json: semester = request.json['semester'] val = dbworker.createClass(request.json['courseTitle'], [], [], [], semester) return jsonify({'success': True})
def deleteHour(): """ Takes in a json of the form {'id' : id of hour log as string} Deletes the hour associated with id Aborts with a 409 in the event that it failed to work in the database """ if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None or 'id' not in request.json: abort(400) convClassId = ObjectId(request.json['id']) res = dbworker.deleteHour(convClassId) if not res: # Failure abort(409) return jsonify({'success': True})
def editUser(): """ Takes in a json of the form {'currentEmail' : email, 'newAttributes' : {...}} It can change any attribute that is not the email """ sys.stderr.write(str(request.json) + '\n') if not dbworker.validateAccess(dbworker.userTypeMap['admin']): abort(403) if request.json is None or 'currentEmail' not in request.json or 'newAttributes' not in request.json: abort(400) email = mailsane.normalize(request.json['currentEmail']) if email.error: abort(400) if dbworker.getUser(str(email)) is None: abort(404) if request.json['newAttributes'] == {} or 'email' in request.json[ 'newAttributes'] or '_id' in request.json['newAttributes']: # No changes requested or an attempt was made to change the email or _id abort(400) # Validate that all the changes made are valid # ie. ban changes to any invalid attributes try: validate(instance=request.json, schema=SchemaFactory.edit_user) except exceptions.ValidationError: abort(400) if 'birthday' in request.json[ 'newAttributes'] or 'password' in request.json['newAttributes']: # Convert birthday from string to datetime object # See https://stackoverflow.com/questions/969285/how-do-i-translate-an-iso-8601-datetime-string-into-a-python-datetime-object correctedTime = None try: if 'birthday' in request.json['newAttributes']: correctedTime = datetime.datetime.strptime( request.json['newAttributes']['birthday'], "%Y-%m-%dT%H:%M:%S.%fZ") except: abort(400) correctedDict = {} for x in request.json['newAttributes']: if x == 'birthday': correctedDict['birthday'] = correctedTime elif x == 'password': dbworker.setPassword(str(email), request.json['newAttributes']['password']) else: correctedDict[x] = request.json['newAttributes'][x] dbworker.editUser(str(email), correctedDict) else: dbworker.editUser(str(email), request.json['newAttributes']) return jsonify({'success': True})