예제 #1
0
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
예제 #2
0
def parsePassword(jsonData):
  try:
    password = jsonData['password']
    return password
  except Exception as e:
    MentiiLogging.getLogger().exception(e)
    return None
예제 #3
0
파일: class_ctrl.py 프로젝트: mentii/mentii
def getClassCodesFromUser(dynamoDBInstance, email=None):
    classCodes = set()
    if email is None:  # pragma: no cover
        email = g.authenticatedUser['email']
    usersTable = dbUtils.getTable('users', dynamoDBInstance)
    if usersTable is None:
        MentiiLogging.getLogger().error(
            'Unable to get users table in getClassCodesFromUser')
    else:
        #An active class list is the list of class codes that
        # a user has in the user table.
        request = {
            "Key": {
                "email": email
            },
            "ProjectionExpression": "classCodes"
        }
        res = dbUtils.getItem(request, usersTable)
        #Get the class codes for the user.
        if res is None or 'Item' not in res or 'classCodes' not in res['Item']:
            MentiiLogging.getLogger().error(
                'Unable to get user data in getClassCodesFromUser')
        else:
            classCodes = res['Item']['classCodes']
    return classCodes
예제 #4
0
파일: class_ctrl.py 프로젝트: mentii/mentii
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
예제 #5
0
파일: algebra.py 프로젝트: mentii/mentii
def getProblem(problemTemplate):
    '''
  Expects a problem template of the form: 
  <template>|<*min range>|<*max range>|<*operator list>

  The template can be any math expression with $a, $b, $c, $d for any numerical value, $var for the variable 'x', $op for a random operator from the operator list.

  The values for the min range, max range, and operator list are optional but if one is provided all values have to be provided. The default values are: -20, 20, and + - * 
  '''
    problem = 'Bad Problem'
    problemTokens = problemTemplate.split('|')
    if len(problemTokens) == 4:
        try:
            template = problemTokens[0]
            minVal = int(problemTokens[1])
            maxVal = int(problemTokens[2])
            opVals = problemTokens[3].split(' ')
            generator = ProblemGenerator(minVal=minVal,
                                         maxVal=maxVal,
                                         opVals=opVals)
            problem = generator.buildProblemFromTemplate(template)
        except Exception as e:
            MentiiLogging.getLogger().exception(e)
    elif len(problemTokens) == 1:
        template = problemTokens[0]
        generator = ProblemGenerator()
        problem = generator.buildProblemFromTemplate(template)
    else:
        MentiiLogging.getLogger().warning(
            'Could not build problem from template: {0}'.format(
                problemTemplate))

    return problem
예제 #6
0
def parseEmail(jsonData):
  try:
    email = jsonData['email']
    return email
  except Exception as e:
    MentiiLogging.getLogger().exception(e)
    return None
예제 #7
0
def chooseProblemTemplate(templateList, userHistoryList):
    '''
  The userHistoryList should be a list of integers
  '''
    index = -1
    problemTemplate = 'Bad Problem'
    if len(templateList) == 0:
        MentiiLogging.getLogger().error("error, empty template list passed")
    else:
        history = [-1 * x for x in userHistoryList]
        #If this function is passed an empty list for userHistoryList
        # then the user did not have a history and it will be initialized
        # inside this if.
        if len(history) != len(templateList):
            history = [0 for _ in xrange(len(templateList))]

        #Normalize the history to be all positive numbers
        minVal = min(history)
        history = [x + abs(minVal) + 1 for x in history]
        #Create a probablility distribution
        total = sum(history)
        probDist = [decimal.Decimal(x) / total for x in history]

        index = choice(range(0, len(templateList)), p=probDist)
        problemTemplate = templateList[index].get('problemString', '')

    return (index, problemTemplate)
예제 #8
0
파일: book_ctrl.py 프로젝트: mentii/mentii
def getBook(bookId, dynamoDBInstance):
    book = None
    booksTable = dbUtils.getTable('books', dynamoDBInstance)
    if booksTable is None:
        MentiiLogging.getLogger().error('Could not get book table')
    else:
        bookQuery = {'Key': {'bookId': bookId}}
        res = dbUtils.getItem(bookQuery, booksTable)
        if res is not None and 'Item' in res.keys():
            book = res['Item']
        else:
            MentiiLogging.getLogger().warning(
                'Could not get an item from the books table')
    return book
예제 #9
0
파일: class_ctrl.py 프로젝트: mentii/mentii
def removeClassFromStudent(dynamoDBInstance, response, email, classCode):
    usersTable = dbUtils.getTable('users', dynamoDBInstance)
    if usersTable is None:
        MentiiLogging.getLogger().error(
            'Unable to get users table in removeStudentFromClass')
        response.addError('Remove Student From Class Failed.',
                          'Unable to locate necessary table(s).')
    else:
        # check that user exists and user has that class
        user = user_ctrl.getUserByEmail(email, dynamoDBInstance)
        if user is None:
            MentiiLogging.getLogger().error(
                'Unable to get user by email in removeStudentFromClass')
            response.addError('Failed to remove student from class',
                              'Unable to find user')
        else:
            classCodes = user['classCodes']  #set
            if classCode not in classCodes:
                response.addError('Failed to remove class from student',
                                  'Class not found')
            else:
                classCodes.remove(classCode)
                jsonData = buildUpdateJsonData('email', email, 'classCodes',
                                               classCodes)
                res = dbUtils.updateItem(jsonData, usersTable)
                if res is None:
                    MentiiLogging.getLogger().error(
                        'Unable to update classes in removeStudentFromClass')
                    response.addError('Failed to remove student from class',
                                      'Unable to update user data')
                else:
                    MentiiLogging.getLogger().info(
                        'Class removal success. Removed class from student')
    return response
예제 #10
0
파일: class_ctrl.py 프로젝트: mentii/mentii
def getClassByCode(classCode, dynamoDBInstance):
    classData = None
    classTable = dbUtils.getTable('classes', dynamoDBInstance)
    if not classTable:
        MentiiLogging.getLogger().error(
            'Unable to access class table in getClassByCode')
    else:
        request = {'Key': {'code': classCode}}
        res = dbUtils.getItem(request, classTable)
        if not res or 'Item' not in res:
            MentiiLogging.getLogger().error(
                'Unable to load class data in getClassByCode')
        else:
            classData = res['Item']
    return classData
예제 #11
0
def getUserByEmail(email, dbInstance):
  user = None

  table = dbUtils.getTable('users', dbInstance)
  if table is None:
    MentiiLogging.getLogger().error('Unable to get table users in getUserByEmail')
  else:
    key = {'Key' : {'email': email}}
    result = dbUtils.getItem(key, table)
    if result is None:
      MentiiLogging.getLogger().error('Unable to get the user with email: ' + email + ' in getUserByEmail ')
    elif 'Item' in result.keys():
      user = result['Item']

  return user
예제 #12
0
파일: MentiiAuth.py 프로젝트: mentii/mentii
def buildUserObject(userData):
    '''
  Builds a standard user object to return to the client for all authenticated calls
  '''
    if not userDataValid(userData):
        # Anything other than raising an exception here would be a security flaw.
        # If the code executes to this point and userData does not contain an email
        # then something is very bad. If only 'None' was returned then the faulty
        # user would still be given access to resources that they shouldnt be allowed
        MentiiLogging.getLogger().error(
            'Invalid User Data for buildUserObject:' + str(userData))
        raise ValueError(
            'This should not be called anywhere other than within MentiiAuthentication. If email is not an attribute of userData then somehow the user has managed to bypass authentication without an email and should be stopped.'
        )
    else:
        return {'email': userData['email'], 'userRole': userData['userRole']}
예제 #13
0
파일: class_ctrl.py 프로젝트: mentii/mentii
def getTaughtClassCodesFromUser(dynamoDBInstance, email=None):
    classCodes = None
    if email is None:  # pragma: no cover
        email = g.authenticatedUser['email']
    usersTable = dbUtils.getTable('users', dynamoDBInstance)
    if usersTable is None:
        MentiiLogging.getLogger().error(
            'Unable to get users table in getTaughtClassCodesFromUser')
    else:
        #An active class list is the list of class codes that
        # a user has in the user table.
        request = {'Key': {'email': email}, 'ProjectionExpression': 'teaching'}
        res = dbUtils.getItem(request, usersTable)
        #Get the class codes for the user.
        if res is not None and 'Item' in res:
            classCodes = res['Item'].get('teaching', [])
    return classCodes
예제 #14
0
파일: class_ctrl.py 프로젝트: mentii/mentii
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
예제 #15
0
파일: book_ctrl.py 프로젝트: mentii/mentii
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
예제 #16
0
파일: MentiiAuth.py 프로젝트: mentii/mentii
def generateAuthToken(userCredentials, appSecret=None, expiration=86400):
    '''
  Generates the auth token based off of the user's email and password with a default expiration duration.
  Default token will last 1 day.
  '''
    if appSecret == None:
        raise ValueError('appSecret cannot be none')
    retval = None
    if userCredentialsValid(userCredentials):
        try:
            s = Serializer(appSecret, expires_in=expiration)
            retval = s.dumps({
                'email': userCredentials['email'],
                'password': userCredentials['password'],
                'userRole': userCredentials['userRole']
            })
        except Exception as e:
            MentiiLogging.getLogger().exception(e)
            retval = None
    return retval
예제 #17
0
def getRole(userEmail, dynamoDBInstance):
  '''
  Returns the role of the user whose email is pased. If we are unable to get
  this information from the DB the role None is returned. Calling code must
  grant only student permissions in this case.
  '''

  userRole = None
  table = dbUtils.getTable('users', dynamoDBInstance)
  if table is None:
    MentiiLogging.getLogger().error('Could not get user table in getUserRole')
  else:
    request = {"Key" : {"email": userEmail}, "ProjectionExpression": "userRole"}
    res = dbUtils.getItem(request, table)
    if res is None or 'Item' not in res:
      MentiiLogging.getLogger().error('Could not get role for user ' + userEmail)
    else:
      userRole = res['Item']['userRole']

  return userRole
예제 #18
0
파일: MentiiAuth.py 프로젝트: mentii/mentii
def verifyAuthToken(token, dbInstance, appSecret=None):
    '''
  Reads the auth token to make sure it has not been modified and that it is not expired
  '''
    if appSecret == None:
        raise ValueError('appSecret cannot be none')
    retval = None
    s = Serializer(appSecret)
    try:
        user = s.loads(token)
        email = user['email']
        password = user['password']
        userFromDB = user_ctrl.getUserByEmail(email, dbInstance)
        if isPasswordValid(userFromDB, password) == True:
            retval = user  # user from token
        else:
            raise BadSignature('Token password did not match stored password')
    except (SignatureExpired, BadSignature) as e:
        MentiiLogging.getLogger().warning(e)
        retval = None
    return retval
예제 #19
0
def addUserAndSendEmail(httpOrigin, email, password, mailer, dbInstance):
  activationId = str(uuid.uuid4())
  table = dbUtils.getTable('users', dbInstance)

  jsonData = {
    'email': email,
    'password': password,
    'activationId': activationId,
    'active': 'F',
    'userRole' : "student"
  }
  if table is None:
    MentiiLogging.getLogger().error('Unable to get table users in addUserAndSendEmail')
    activationId = None

  #This will change an existing user with the same email.
  response = dbUtils.putItem(jsonData,table)

  if response is None:
    MentiiLogging.getLogger().error('Unable to add user to table users in addUserAndSendEmail')
    activationId = None

  try:
    sendEmail(httpOrigin, email, activationId, mailer)
  except Exception as e:
    MentiiLogging.getLogger().exception(e)

  return activationId
예제 #20
0
def getBookInfoFromActivity(classId, activityTitle, dynamoDBInstance):
    classItem = {}
    bookId = ''
    chapterTitle = ''
    sectionTitle = ''
    classTable = dbUtils.getTable('classes', dynamoDBInstance)
    if classTable is None:
        MentiiLogging.getLogger().warning('Could not get the class table')
    else:
        classQuery = {'Key': {'code': classId}}
        res = dbUtils.getItem(classQuery, classTable)
        if res is not None and 'Item' in res.keys():
            classItem = res['Item']

    for activity in classItem.get('activities', []):
        if activity.get('title', '') == activityTitle:
            bookId = activity.get('bookId', '')
            chapterTitle = activity.get('chapterTitle', '')
            sectionTitle = activity.get('sectionTitle', '')
            break  #Only get the first activity with this title

    return (bookId, chapterTitle, sectionTitle)
예제 #21
0
파일: class_ctrl.py 프로젝트: mentii/mentii
def removeStudentFromClass(dynamoDBInstance, response, email, classCode):
    classesTable = dbUtils.getTable('classes', dynamoDBInstance)
    if classesTable is None:
        MentiiLogging.getLogger().error(
            'Unable to get classes table in removeStudentFromClass')
        response.addError('Remove Student From Class Failed.',
                          'Unable to locate necessary table(s).')
    else:
        # check that class exists and class has that user
        cl = getClassByCode(classCode, dynamoDBInstance)
        if cl is None:
            MentiiLogging.getLogger().error(
                'Unable to get class by classCode in removeStudentFromClass')
            response.addError('Failed to remove student from class',
                              'Unable to get class')
        else:
            students = cl['students']  #set
            if email not in students:
                response.addError('Failed to remove student from class',
                                  'Student not found')
            else:
                students.remove(email)
                jsonData = buildUpdateJsonData('code', classCode, 'students',
                                               students)
                res = dbUtils.updateItem(jsonData, classesTable)
                if res is None:
                    MentiiLogging.getLogger().error(
                        'Unable to update classes in removeStudentFromClass')
                    response.addError('Failed to remove student from class',
                                      'Unable to update classes data')
                if response.hasErrors():
                    undoClassCodeRemoval(dynamoDBInstance, email, classCode)
                else:
                    MentiiLogging.getLogger().info(
                        'Student removal success. Removed student from class')
    return response
예제 #22
0
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
예제 #23
0
파일: app.py 프로젝트: mentii/mentii
import boto3
import ConfigParser as cp
import sys

#Configuration setup
configPath = "/config/prodConfig.ini"
if len(sys.argv) == 2:
  configPath = sys.argv[1]

#Parse any external configuration options
parser = cp.ConfigParser()
parser.read(configPath)

#Setup logfile
logPath = parser.get('LogfileLocation', 'path') + '/logs'
MentiiLogging.setupLogger(logPath)
logger = MentiiLogging.getLogger()

#Start Flask App
app = Flask(__name__)
cors = CORS(app, resources={r"/*": {"origins": "*"}})
mail = Mail(app)
auth = HTTPBasicAuth()

#Email setup
address = parser.get('EmailData', 'address')
password = parser.get('EmailData', 'password')
appSecret = parser.get('MentiiAuthentication', 'appSecret')

#Database configuration
prod = parser.get('DatabaseData', 'isProd')
예제 #24
0
파일: class_ctrl.py 프로젝트: mentii/mentii
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
예제 #25
0
 def addError(self, title, message):
   MentiiLogging.getLogger().error('%s : %s', title, message)
   tmpErrorDict = {"title" : title, "message" : message}
   self.errors.append(tmpErrorDict)
   self.hasError = True