def updateUserTemplateHistory(classId, activity, userId, index, didSucceed, dynamoDBInstance): #Get the section so we can update the weights response = ControllerResponse() bookId, chapterTitle, sectionTitle = getBookInfoFromActivity( classId, activity, dynamoDBInstance) section = book_ctrl.getSectionFromBook(bookId, chapterTitle, sectionTitle, dynamoDBInstance) #Update the weights or create new ones if this is the first time currentWeights = section.get('users', {}).get(userId, []) newWeights = [0 for _ in xrange(len(section.get('problems', []))) ] #Initial value if len(currentWeights) != 0: #Update if we can newWeights = currentWeights #Actually update the weights if index < len(newWeights): if didSucceed: newWeights[index] += 1 else: newWeights[index] -= 1 #Send it elsewhere to update the database updateSuccessful = book_ctrl.updateBookWithUserData( bookId, chapterTitle, sectionTitle, userId, newWeights, dynamoDBInstance) if not updateSuccessful: response.addError('History Update Error', 'Unable to update the users history') return response
def activate(activationId, dbInstance): response = ControllerResponse() table = dbUtils.getTable('users', dbInstance) items = [] if table is None: MentiiLogging.getLogger().error('Unable to get table users in activate') response.addError('Could not access table. Error', 'The DB did not give us the table') return response #Scan for the email associated with this activationId scanResponse = dbUtils.scanFilter('activationId', activationId, table) if scanResponse is not None: #scanResponse is a dictionary that has a list of 'Items' items = scanResponse['Items'] if not items or 'email' not in items[0].keys(): response.addError('No user with activationid', 'The DB did not return a user with the passed in activationId') else: email = items[0]['email'] jsonData = { 'Key': {'email': email}, 'UpdateExpression': 'SET active = :a', 'ExpressionAttributeValues': { ':a': 'T' }, 'ReturnValues' : 'UPDATED_NEW' } #Update using the email we have res = dbUtils.updateItem(jsonData, table) response.addToPayload('status', 'Success') return response
def leaveClass(jsonData, dynamoDBInstance, email=None): response = ControllerResponse() data = None if g: # pragma: no cover email = g.authenticatedUser['email'] if 'code' not in jsonData.keys() or not jsonData['code']: response.addError('Key Missing Error', 'class code missing from data') else: classCode = jsonData['code'] data = { 'email': email, 'classCode': classCode } return class_ctrl.removeStudent(dynamoDBInstance, data, response=response, userRole=None)
def test_addDataToClassAndUser(self): userRole = 'student' email = '*****@*****.**' classCode = 'abcef12345' title = 'some class' response = ControllerResponse() # add student to user table usersTable = db.getTable('users', dynamodb) jsonData = {'email': email} db.putItem(jsonData, usersTable) # add class to class table classesTable = db.getTable('classes', dynamodb) jsonData = {'code': classCode, 'title': title} db.putItem(jsonData, classesTable) usr.addDataToClassAndUser(classCode, email, response, dynamodb) self.assertFalse(response.hasErrors()) self.assertEqual(response.payload['title'], title) self.assertEqual(response.payload['code'], classCode)
def resetUserPassword(jsonData, dbInstance): response = ControllerResponse() email = jsonData.get('email', None) password = jsonData.get('password', None) resetPasswordId = jsonData.get('id', None) if email is not None and password is not None and resetPasswordId is not None: res = updatePasswordForEmailAndResetId(email, password, resetPasswordId, dbInstance) if res is not None: response.addToPayload('status', 'Success') else: response.addError('Failed to Reset Password', 'We were unable to update the password for this account.') else: response.addError('Failed to Reset Password', 'We were unable to update the password for this account.') return response
def editBook(bookData, dynamoDBInstance): response = ControllerResponse() # check for required options if not bookData or 'title' not in bookData.keys( ) or 'description' not in bookData.keys() or 'bookId' not in bookData.keys( ): response.addError('Book update failed.', 'Invalid book data given.') else: # Get books table booksTable = dbUtils.getTable('books', dynamoDBInstance) if booksTable is None: response.addError('Get Books Table Failed', 'Unable to get books table from database') else: # put item into table result = dbUtils.putItem(bookData, booksTable) if result is None: response.addError('Book update failed.', 'Unable to update Book in database.') else: response.addToPayload('Success', 'Book Updated') return response
def test_resetUserPasswordFuncPoorData(self): usr.addResetPasswordIdToUser('*****@*****.**', 'test-reset-id', dynamodb) user = usr.getUserByEmail('*****@*****.**', dynamodb) userResetId = user.get('resetPasswordId', None) self.assertIsNotNone(userResetId) userPassword = user.get('password', None) updatedUser = {'email': "*****@*****.**"} res = usr.resetUserPassword(updatedUser, dynamodb) badResJson = '{"errors": [{"message": "We were unable to update the password for this account.", "title": "Failed to Reset Password"}], "user": {}, "payload": {}}' resJson = ControllerResponse.getResponseString(res) self.assertEqual(resJson, badResJson) updatedUser = usr.getUserByEmail('*****@*****.**', dynamodb) updatedResetId = updatedUser.get('resetPasswordId', None) self.assertIsNotNone(updatedResetId) updatedPassword = updatedUser.get('password', None) self.assertEqual(userPassword, updatedPassword)
def getPublicClassList(dynamodb, email=None): response = ControllerResponse() classCodes = getClassCodesFromUser(dynamodb, email) classes = [] classesTable = dbUtils.getTable('classes', dynamodb) if classesTable is None: MentiiLogging.getLogger().error( 'Unable to get classes table in getPublicClassList') response.addError('Failed to get class list', 'A database error occured') else: res = classesTable.scan() for pclass in res.get('Items', []): if pclass[ 'code'] not in classCodes and 'private' not in pclass and pclass.get( 'private') != True: classes.append(pclass) response.addToPayload('classes', classes) return response
def getProblemTree(problemTemplate): #When problem templates work problem could # be a problem template instead. If that's the case # we could get the problem from the template here response = ControllerResponse() numberOfFailurePoints = 2 #TODO: Replace this with the recommender system output problem = getProblem(problemTemplate) problemPath = mathsteps.getStepsForProblem(problem) if len(problemPath) <= 1: #We couldn't get a path for the problem response.addError( 'Problem Solve Error', 'Could not generate path for problem {0}'.format(problem)) else: problemTree = generateTreeWithBadSteps(problemPath, numberOfFailurePoints) response.addToPayload('problemTree', problemTree) return response
def getBookList(dynamoDBInstance): response = ControllerResponse() booksTable = dbUtils.getTable('books', dynamoDBInstance) if booksTable is None: MentiiLogging.getLogger().error('Could not get book table') response.addError('Failed to get book list', 'A database error occured') else: books = dbUtils.scan(booksTable) bookList = [] if books is not None and 'Items' in books: for book in books.get('Items'): bookList.append({ 'id': book.get('bookId'), 'title': book.get('title') }) response.addToPayload('books', bookList) else: MentiiLogging.getLogger().warning('Could not scan books table') return response
def joinClass(jsonData, dynamoDBInstance, email=None, userRole=None): response = ControllerResponse() #g will be not be available during testing #and email will need to be passed to the function if g: # pragma: no cover email = g.authenticatedUser['email'] userRole = g.authenticatedUser['userRole'] if 'code' not in jsonData.keys() or not jsonData['code']: response.addError('Key Missing Error', 'class code missing from data') elif userRole == 'teacher' or userRole == 'admin': if class_ctrl.isCodeInTaughtList(jsonData, dynamoDBInstance, email): response.addError('Role Error', 'Teachers cannot join their taught class as a student') else: classCode = jsonData['code'] addDataToClassAndUser(classCode, email, response, dynamoDBInstance) else: classCode = jsonData['code'] addDataToClassAndUser(classCode, email, response, dynamoDBInstance) return response
def getTaughtClassList(dynamoDBInstance, email=None): response = ControllerResponse() if email is None: # pragma: no cover email = g.authenticatedUser['email'] usersTable = dbUtils.getTable('users', dynamoDBInstance) classTable = dbUtils.getTable('classes', dynamoDBInstance) if usersTable is None or classTable is None: response.addError('Get Taught Class List Failed', 'Unable to access users and/or classes') else: classes = [] classCodes = getTaughtClassCodesFromUser(dynamoDBInstance, email) if classCodes is not None: for code in classCodes: request = {'Key': {'code': code}} res = dbUtils.getItem(request, classTable) if res is not None and 'Item' in res: classes.append(res['Item']) response.addToPayload('classes', classes) return response
def removeStudent(dynamoDBInstance, jsonData, response=None, userRole=None): currentUserEmail = None if response is None: response = ControllerResponse() email = jsonData.get('email') classCode = jsonData.get('classCode') if g: userRole = g.authenticatedUser['userRole'] currentUserEmail = g.authenticatedUser['email'] if not (userRole == 'teacher' or userRole == 'admin' or currentUserEmail == email): response.addError( 'Role error', 'Only those with teacher privileges can remove students from classes' ) elif email is None or classCode is None: response.addError('Failed to remove student from class', 'Invalid data given') else: removeClassFromStudent(dynamoDBInstance, response, email, classCode) if not response.hasErrors(): removeStudentFromClass(dynamoDBInstance, response, email, classCode) return response
def getClass(classCode, dynamoDBInstance, email=None, userRole=None): response = ControllerResponse() classData = getClassByCode(classCode, dynamoDBInstance) if not classData: response.addError('Get Class Failed', 'Unable to load class data') else: if g: # pragma: no cover email = g.authenticatedUser['email'] userRole = g.authenticatedUser['userRole'] #Checks that user is the teacher of the class w/ classCode if ((userRole == 'teacher' or userRole == 'admin') and classCode in getTaughtClassCodesFromUser( dynamoDBInstance, email)): classData['isTeacher'] = True #Else remove students[] from classData, if it exists, because: #Only the teacher of a class can get the class's students elif 'students' in classData: if email in classData.get('students', []): classData['isStudent'] = True del classData['students'] response.addToPayload('class', classData) return response
def createBook(bookData, dynamoDBInstance, userRole=None): response = ControllerResponse() #g will be not be available during testing #userRole will need to be passed to the function if g: # pragma: no cover userRole = g.authenticatedUser['userRole'] #role is confirmed here incase createBook is called from somewhere other #than app.py createBook() if userRole != 'admin': response.addError('Role error', 'Only admins can create books') # check for required options elif 'title' not in bookData.keys() or 'description' not in bookData.keys( ): response.addError('Book creation failed.', 'Invalid book data given.') else: # Get books table booksTable = dbUtils.getTable('books', dynamoDBInstance) if booksTable is None: response.addError('Get Books Table Failed', 'Unable to get books table from database') else: bookId = str(uuid.uuid4()) # prep json data book = { 'bookId': bookId, 'title': bookData['title'], 'description': bookData['description'], 'chapters': bookData.get('chapters', []) } # put item into table result = dbUtils.putItem(book, booksTable) if result is None: response.addError('Book creation failed.', 'Unable to create Book in database.') else: response.addToPayload('Success', 'Book Created') return response
def register(httpOrigin, jsonData, mailer, dbInstance): response = ControllerResponse() if not validateRegistrationJSON(jsonData): response.addError('Register Validation Error', 'The json data did not have an email or did not have a password') else: email = parseEmail(jsonData) password = parsePassword(jsonData) if not isEmailValid(email): response.addError('Email invalid', 'The email is invalid') if not isPasswordValid(password): response.addError('Password Invalid', 'The password is invalid') if isEmailInSystem(email, dbInstance) and isUserActive(getUserByEmail(email, dbInstance)): response.addError('Registration Failed', 'We were unable to register this user') if not response.hasErrors(): hashedPassword = hashPassword(parsePassword(jsonData)) activationId = addUserAndSendEmail(httpOrigin, email, hashedPassword, mailer, dbInstance) if activationId is None: response.addError('Activation Id is None', 'Could not create an activation Id') return response
def updateClassDetails(jsonData, dynamodb, email=None, userRole=None): response = ControllerResponse() classesTable = dbUtils.getTable('classes', dynamodb) if classesTable is None: MentiiLogging.getLogger().error( 'Unable to get classes table in getPublicClassList') response.addError('Failed to get class list', 'A database error occured') else: # get data from request body code = jsonData.get('code') title = jsonData.get('title') desc = jsonData.get('description') dept = jsonData.get('department') # optional sec = jsonData.get('section') # optional if g: # pragma: no cover email = g.authenticatedUser['email'] userRole = g.authenticatedUser['userRole'] #check if teacher is teacher of the class if ((userRole == 'teacher' or userRole == 'admin') and code in getTaughtClassCodesFromUser(dynamodb, email)): updateExprString = 'SET title =:t, description =:dn' expresionAttrDict = {':t': title, ':dn': desc} removeString = '' # if empty string is given, remove the attribute if dept == '' and sec == '': removeString = removeString + ' REMOVE department, classSection' else: if dept == '': removeString = removeString + ' REMOVE department' else: updateExprString = updateExprString + ', department = :dt' expresionAttrDict[':dt'] = dept if sec == '': removeString = removeString + ' REMOVE classSection' else: updateExprString = updateExprString + ', classSection = :s' expresionAttrDict[':s'] = sec updateExprString = updateExprString + removeString # update item updateData = { 'Key': { 'code': code }, 'UpdateExpression': updateExprString, 'ExpressionAttributeValues': expresionAttrDict, 'ReturnValues': 'UPDATED_NEW' } res = dbUtils.updateItem(updateData, classesTable) if res is None: response.addError('updateClassDetails has error', 'Unable to update class details') else: response.addToPayload('Success', 'Class Details Updated') else: response.addError('Teacher permissions incorrect', 'Unable to update class details') return response
def changeUserRole(jsonData, dbInstance, adminRole=None): response = ControllerResponse() #g will be not be available during testing #and adminRole will need to be passed to the function if g: # pragma: no cover adminRole = g.authenticatedUser['userRole'] #adminRole is confirmed here incase changeUserRole is called from somewhere #other than app.py changeUserRole() if adminRole != 'admin': response.addError('Role Error', 'Only admins can change user roles') elif 'email' not in jsonData.keys() or 'userRole' not in jsonData.keys(): response.addError('Key Missing Error', 'Email or role missing from json data') else: email = jsonData['email'] userRole = jsonData['userRole'] userTable = dbUtils.getTable('users', dbInstance) if userTable is None: MentiiLogging.getLogger().error('Unable to get table "users" in changeUserRole') response.addError('No Access to Data', 'Unable to get data from database') else: if userRole != 'student' and userRole != 'teacher' and userRole != 'admin': MentiiLogging.getLogger().error('Invalid role: ' + userRole + ' specified. Unable to change user role') response.addError('Invalid Role Type', 'Invaid role specified') else: data = { 'Key': {'email': email}, 'UpdateExpression': 'SET userRole = :ur', 'ExpressionAttributeValues': { ':ur': userRole }, 'ReturnValues' : 'UPDATED_NEW' } result = dbUtils.updateItem(data, userTable) if result is None: MentiiLogging.getLogger().error('Unable to update the user with email: ' + email + ' in changeUserRole') response.addError('Result Update Error', 'Could not update the user role in database') else: response.addToPayload('Result:', result) response.addToPayload('success', 'true') return response
def addActivity(classCode, jsonData, dynamodb, email=None, userRole=None): response = ControllerResponse() classTable = dbUtils.getTable('classes', dynamodb) if classTable is None: MentiiLogging.getLogger().error( 'Unable to get classes table in getPublicClassList') response.addError('Failed to add activity', 'A database error occured') else: if g: # pragma: no cover email = g.authenticatedUser['email'] userRole = g.authenticatedUser['userRole'] if isTeacherOfClass(email, userRole, classCode, dynamodb): classData = getClassByCode(classCode, dynamodb) if not classData: response.addError('Failed to add activity', 'A database error occured') else: activities = classData.get('activities', []) activities.append(jsonData) classData['activities'] = activities result = dbUtils.putItem(classData, classTable) if result is None: response.addError('Failed to add activity', 'A database error occured') else: response.addToPayload('Success', 'Activity Added') else: MentiiLogging.getLogger().error( email + ' is not the teacher of ' + classCode + ', but attempted to add an activity.') response.addError('Unable to add activity', 'A permissions error occured') return response
def createClass(dynamoDBInstance, classData, email=None, userRole=None): response = ControllerResponse() #g will be not be available during testing #and email and userRole will need to be passed to the function if g: # pragma: no cover email = g.authenticatedUser['email'] userRole = g.authenticatedUser['userRole'] #role is confirmed here incase createClass is called from somewhere other #than app.py create_class() if userRole != 'teacher' and userRole != 'admin': response.addError('Role error', 'Only teachers can create classes') elif classData is None or not checkClassDataValid(classData): response.addError('createClass call Failed.', 'Invalid class data given.') else: classTable = dbUtils.getTable('classes', dynamoDBInstance) userTable = dbUtils.getTable('users', dynamoDBInstance) if classTable is None or userTable is None: response.addError('createClass call Failed.', 'Unable to locate necessary table(s).') else: classCode = str(uuid.uuid4()) newClass = { 'code': classCode, 'title': classData['title'], 'description': classData['description'] } if 'department' in classData.keys() and classData['department']: newClass['department'] = classData['department'] if 'section' in classData.keys() and classData['section']: newClass['classSection'] = classData['section'] result = dbUtils.putItem(newClass, classTable) if result is None: response.addError('createClass call Failed.', 'Unable to create class in classes table.') else: # Note: if teaching attribute does not previously exist, a set of class codes will be created # otherwise, the class code will be added to the set of class codes codeSet = set([classCode]) jsonData = { 'Key': { 'email': email }, 'UpdateExpression': 'ADD teaching :classCode', 'ExpressionAttributeValues': { ':classCode': codeSet }, 'ReturnValues': 'UPDATED_NEW' } res = dbUtils.updateItem(jsonData, userTable) if res is None: response.addError('createClass call failed', 'Unable to update user data') else: response.addToPayload('Success', 'Class Created') return response