def resetPassword(self,system_email,session):
        """

        Remove old password and email user a token to set a new password.  Request should have key "email"

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask

        """
        requestDict = RequestDictionary(self.request)
        if(not (requestDict.exists("email"))):
            # Don't have the keys we need in request
            exc = ResponseException("Reset password route requires key 'email'",StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        # Get user object
        try:
            user = self.interfaces.userDb.getUserByEmail(requestDict.getValue("email"))
        except Exception as e:
            exc = ResponseException("Unknown Error",StatusCode.CLIENT_ERROR,ValueError)
            return JsonResponse.error(exc,exc.status)

        email = requestDict.getValue("email")
        LoginSession.logout(session)
        self.sendResetPasswordEmail(user, system_email, email)

        # Return success message
        return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
예제 #2
0
        def decorated_function(*args, **kwargs):
            errorMessage = "Login Required"
            if LoginSession.isLogin(session):
                userDb = UserHandler()
                try:
                    user = userDb.getUserByUID(session["name"])
                    validUser = True
                    for permission in permissionList:
                        if (not userDb.hasPermission(user, permission)):
                            validUser = False
                finally:
                    InterfaceHolder.closeOne(userDb)
                if (validUser):
                    return f(*args, **kwargs)
                errorMessage = "Wrong User Type"
            elif "check_email_token" in permissionList:
                if (LoginSession.isRegistering(session)):
                    return f(*args, **kwargs)
                else:
                    errorMessage = "unauthorized"
            elif "check_password_token" in permissionList:
                if (LoginSession.isResetingPassword(session)):
                    return f(*args, **kwargs)
                else:
                    errorMessage = "unauthorized"

            returnResponse = flask.Response()
            returnResponse.headers["Content-Type"] = "application/json"
            returnResponse.status_code = 401  # Error code
            responseDict = {}
            responseDict["message"] = errorMessage
            returnResponse.set_data(json.dumps(responseDict))
            return returnResponse
    def checkPasswordToken(self,session):
        """

        Checks the password token if its valid

        arguments:

        session -- (Session) object from flask

        return the reponse object with a error code and a message

        """
        request_fields = RequestDictionary.derive(self.request)
        try:
            if 'token' not in request_fields:
                raise ResponseException(
                    "Request body must include token", StatusCode.CLIENT_ERROR)
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)
        token = request_fields['token']
        # Save token to be deleted after reset
        session["token"] = token
        success, message, errorCode = sesEmail.check_token(token, "password_reset")
        if success:
            #mark session that password can be filled out
            LoginSession.reset_password(session)

            return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"})
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
    def reset_password(self,system_email,session):
        """

        Remove old password and email user a token to set a new password.  Request should have key "email"

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask

        """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        try:
            if 'email' not in request_dict:
                # Don't have the keys we need in request
                raise ResponseException(
                    "Reset password route requires key 'email'",
                    StatusCode.CLIENT_ERROR
                )
            user = sess.query(User).filter(
                func.lower(User.email) == func.lower(request_dict['email'])
            ).one()
        except Exception as exc:
            return JsonResponse.error(exc, StatusCode.CLIENT_ERROR)

        email = request_dict['email']
        LoginSession.logout(session)
        self.send_reset_password_email(user, system_email, email)

        # Return success message
        return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
예제 #5
0
    def checkPasswordToken(self, session):
        """

        Checks the password token if its valid

        arguments:

        session -- (Session) object from flask

        return the reponse object with a error code and a message

        """
        requestFields = RequestDictionary(self.request)
        if (not requestFields.exists("token")):
            exc = ResponseException("Request body must include token",
                                    StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc, exc.status)
        token = requestFields.getValue("token")
        success, message, errorCode = sesEmail.checkToken(
            token, self.interfaces.userDb, "password_reset")
        if (success):
            #mark session that password can be filled out
            LoginSession.resetPassword(session)

            return JsonResponse.create(StatusCode.OK, {
                "email": message,
                "errorCode": errorCode,
                "message": "success"
            })
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK, {
                "errorCode": errorCode,
                "message": message
            })
        def decorated_function(*args, **kwargs):
            errorMessage = "Login Required"
            if LoginSession.isLogin(session):
                userDb = UserHandler()
                try:
                    user = userDb.getUserByUID(session["name"])
                    validUser = True
                    for permission in permissionList:
                        if not userDb.hasPermission(user, permission):
                            validUser = False
                finally:
                    InterfaceHolder.closeOne(userDb)
                if validUser:
                    return f(*args, **kwargs)
                errorMessage = "Wrong User Type"
            elif "check_email_token" in permissionList:
                if LoginSession.isRegistering(session):
                    return f(*args, **kwargs)
                else:
                    errorMessage = "unauthorized"
            elif "check_password_token" in permissionList:
                if LoginSession.isResetingPassword(session):
                    return f(*args, **kwargs)
                else:
                    errorMessage = "unauthorized"

            returnResponse = flask.Response()
            returnResponse.headers["Content-Type"] = "application/json"
            returnResponse.status_code = 401  # Error code
            responseDict = {}
            responseDict["message"] = errorMessage
            returnResponse.set_data(json.dumps(responseDict))
            return returnResponse
    def checkEmailConfirmationToken(self,session):
        """

        Creates user record and email

        arguments:

        session -- (Session) object from flask

        return the reponse object with a error code and a message

        """
        requestFields = RequestDictionary(self.request)
        if(not requestFields.exists("token")):
            exc = ResponseException("Request body must include token", StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        token = requestFields.getValue("token")
        success,message,errorCode = sesEmail.checkToken(token,self.interfaces.userDb,"validate_email")
        if(success):
            #mark session that email can be filled out
            LoginSession.register(session)

            #remove token so it cant be used again
            # The following line is commented out for issues with registration email links bouncing users back
            # to the original email input page instead of the registration page
            #self.interfaces.userDb.deleteToken(token)

            #set the status only if current status is awaiting confirmation
            user = self.interfaces.userDb.getUserByEmail(message)
            if self.interfaces.userDb.checkStatus(user,"awaiting_confirmation"):
                self.interfaces.userDb.changeStatus(user,"email_confirmed")
            return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"})
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
예제 #8
0
    def resetPassword(self, system_email, session):
        """

        Remove old password and email user a token to set a new password.  Request should have key "email"

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask

        """
        requestDict = RequestDictionary(self.request)
        if (not (requestDict.exists("email"))):
            # Don't have the keys we need in request
            exc = ResponseException(
                "Reset password route requires key 'email'",
                StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc, exc.status)
        # Get user object
        try:
            user = self.interfaces.userDb.getUserByEmail(
                requestDict.getValue("email"))
        except Exception as e:
            exc = ResponseException("Unknown Error", StatusCode.CLIENT_ERROR,
                                    ValueError)
            return JsonResponse.error(exc, exc.status)

        email = requestDict.getValue("email")
        LoginSession.logout(session)
        self.sendResetPasswordEmail(user, system_email, email)

        # Return success message
        return JsonResponse.create(StatusCode.OK,
                                   {"message": "Password reset"})
    def checkPasswordToken(self,session):
        """

        Checks the password token if its valid

        arguments:

        session -- (Session) object from flask

        return the reponse object with a error code and a message

        """
        requestFields = RequestDictionary(self.request)
        if(not requestFields.exists("token")):
            exc = ResponseException("Request body must include token", StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        token = requestFields.getValue("token")
        success,message,errorCode = sesEmail.checkToken(token,self.interfaces.userDb,"password_reset")
        if(success):
            #mark session that password can be filled out
            LoginSession.resetPassword(session)

            return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"})
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
    def resetPassword(self,system_email,session):
        """

        Remove old password and email user a token to set a new password.  Request should have key "email"

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask

        """
        requestDict = RequestDictionary(self.request)
        if(not (requestDict.exists("email"))):
            # Don't have the keys we need in request
            exc = ResponseException("Reset password route requires key 'email'",StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        # Get user object
        try:
            user = self.interfaces.userDb.getUserByEmail(requestDict.getValue("email"))
        except Exception as e:
            exc = ResponseException("Unknown Error",StatusCode.CLIENT_ERROR,ValueError)
            return JsonResponse.error(exc,exc.status)

        LoginSession.logout(session)
        self.interfaces.userDb.session.commit()
        email = requestDict.getValue("email")
        # Send email with token
        emailToken = sesEmail.createToken(email,self.interfaces.userDb,"password_reset")
        link= "".join([ AccountHandler.FRONT_END,'#/forgotpassword/',emailToken])
        emailTemplate = { '[URL]':link}
        newEmail = sesEmail(user.email, system_email,templateType="reset_password",parameters=emailTemplate,database=self.interfaces.userDb)
        newEmail.send()
        # Return success message
        return JsonResponse.create(StatusCode.OK,{"message":"Password reset"})
    def login(self,session):
        """

        Logs a user in if their password matches

        arguments:

        session  -- (Session) object from flask

        return the reponse object

        """
        try:
            safeDictionary = RequestDictionary(self.request)

            username = safeDictionary.getValue('username')

            password = safeDictionary.getValue('password')

            try:
                user  = self.interfaces.userDb.getUserByEmail(username)
            except Exception as e:
                raise ValueError("user name and or password invalid")

            if(not self.interfaces.userDb.checkStatus(user,"approved")):
                raise ValueError("user name and or password invalid")

            # Only check if user is active after they've logged in for the first time
            if user.last_login_date is not None and not self.isUserActive(user):
                raise ValueError("Your account has expired. Please contact an administrator.")

            try:
                if(self.interfaces.userDb.checkPassword(user,password,self.bcrypt)):
                    # We have a valid login
                    LoginSession.login(session,user.user_id)
                    permissionList = []
                    for permission in self.interfaces.userDb.getPermssionList():
                        if(self.interfaces.userDb.hasPermission(user, permission.name)):
                            permissionList.append(permission.permission_type_id)
                    self.interfaces.userDb.updateLastLogin(user)
                    return JsonResponse.create(StatusCode.OK,{"message":"Login successful","user_id": int(user.user_id),"name":user.name,"title":user.title ,"agency":user.agency, "permissions" : permissionList})
                else :
                    raise ValueError("user name and or password invalid")
            except Exception as e:
                    LoginSession.logout(session)
                    raise ValueError("user name and or password invalid")

        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e,StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e,StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
        return self.response
        def decorated_function(*args, **kwargs):
            try:
                sess = GlobalDB.db().session
                error_message = "Login Required"
                if permission == "check_email_token":
                    if LoginSession.isRegistering(session):
                        return f(*args, **kwargs)
                    else:
                        error_message = "unauthorized"
                elif permission == "check_password_token":
                    if LoginSession.isResetingPassword(session):
                        return f(*args, **kwargs)
                    else:
                        error_message = "unauthorized"
                elif LoginSession.isLogin(session):
                    user = sess.query(User).filter(
                        User.user_id == session["name"]).one()
                    valid_user = True

                    if permission is not None:
                        perm_hierarchy = {
                            d['name']: d['order']
                            for d in PERMISSION_MAP.values()
                        }
                        # if the users permission is not higher than the one specified, check their permission
                        # if user's perm order is < than what's passed in, it means they have higher permissions
                        if perm_hierarchy[PERMISSION_TYPE_DICT_ID[
                                user.permission_type_id]] > perm_hierarchy[
                                    permission]:
                            if not user.permission_type_id == PERMISSION_TYPE_DICT[
                                    permission]:
                                valid_user = False

                    if valid_user:
                        return f(*args, **kwargs)
                    error_message = "You are not authorized to perform the requested task. Please contact your administrator."

                # No user logged in
                return_response = flask.Response()
                return_response.headers["Content-Type"] = "application/json"
                return_response.status_code = 401  # Error code
                response_dict = {}
                response_dict["message"] = error_message
                return_response.set_data(json.dumps(response_dict))
                return return_response

            except ResponseException as e:
                return JsonResponse.error(e, e.status)
            except InvalidUsage:
                raise
            except Exception as e:
                exc = ResponseException(str(e), StatusCode.INTERNAL_ERROR,
                                        type(e))
                return JsonResponse.error(exc, exc.status)
    def create_session_and_response(self, session, user):
        """Create a session."""
        LoginSession.login(session, user.user_id)

        sess = GlobalDB.db().session
        updateLastLogin(user)
        agency_name = sess.query(CGAC.agency_name).\
            filter(CGAC.cgac_code == user.cgac_code).\
            one_or_none()
        return JsonResponse.create(StatusCode.OK, {"message": "Login successful", "user_id": int(user.user_id),
                                                   "name": user.name, "title": user.title,
                                                   "agency_name": agency_name,
                                                   "cgac_code": user.cgac_code, "permission": user.permission_type_id})
def logout(session):
    """ This function removes the session from the session table if currently logged in, and then returns a success
        message

        Args:
            session: the Session object

        Returns:
            a JsonResponse that the logout was successful
    """
    # Call session handler
    LoginSession.logout(session)
    return JsonResponse.create(StatusCode.OK, {"message": "Logout successful"})
예제 #15
0
def logout(session):
    """ This function removes the session from the session table if currently logged in, and then returns a success
        message

        Args:
            session: the Session object

        Returns:
            a JsonResponse that the logout was successful
    """
    # Call session handler
    LoginSession.logout(session)
    return JsonResponse.create(StatusCode.OK, {"message": "Logout successful"})
    def create_session_and_response(session, user):
        """ Create a session.

            Args:
                session: Session object from flask
                user: Users object

            Returns:
                JsonResponse containing the JSON for the user
        """
        LoginSession.login(session, user.user_id)
        data = json_for_user(user, session['sid'])
        data['message'] = 'Login successful'
        return JsonResponse.create(StatusCode.OK, data)
예제 #17
0
    def create_session_and_response(session, user):
        """ Create a session.

            Args:
                session: Session object from flask
                user: Users object

            Returns:
                JsonResponse containing the JSON for the user
        """
        LoginSession.login(session, user.user_id)
        data = json_for_user(user, session['sid'])
        data['message'] = 'Login successful'
        return JsonResponse.create(StatusCode.OK, data)
    def login(self, session):
        """

        Logs a user in if their password matches

        arguments:

        session  -- (Session) object from flask

        return the response object

        """
        try:
            sess = GlobalDB.db().session
            safe_dictionary = RequestDictionary(self.request)

            username = safe_dictionary.get_value('username')

            password = safe_dictionary.get_value('password')

            try:
                user = sess.query(User).filter(
                    func.lower(User.email) == func.lower(username)).one()
            except Exception:
                raise ValueError("Invalid username and/or password")

            try:
                if check_correct_password(user, password, self.bcrypt):
                    # We have a valid login

                    return self.create_session_and_response(session, user)
                else:
                    raise ValueError("Invalid username and/or password")
            except ValueError as ve:
                LoginSession.logout(session)
                raise ve
            except Exception as e:
                LoginSession.logout(session)
                raise e

        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e, StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e, StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e, StatusCode.INTERNAL_ERROR)
    def logout(self,session):
        """

        This function removes the session from the session table if currently logged in, and then returns a success message

        arguments:

        session  -- (Session) object from flask

        return the reponse object

        """
        # Call session handler
        LoginSession.logout(session)
        return JsonResponse.create(StatusCode.OK,{"message":"Logout successful"})
    def logout(self,session):
        """

        This function removes the session from the session table if currently logged in, and then returns a success message

        arguments:

        session  -- (Session) object from flask

        return the reponse object

        """
        # Call session handler
        LoginSession.logout(session)
        return JsonResponse.create(StatusCode.OK,{"message":"Logout successful"})
    def login(self, session):
        """

        Logs a user in if their password matches

        arguments:

        session  -- (Session) object from flask

        return the response object

        """
        try:
            sess = GlobalDB.db().session
            safe_dictionary = RequestDictionary(self.request)

            username = safe_dictionary.get_value('username')

            password = safe_dictionary.get_value('password')

            try:
                user = sess.query(User).filter(func.lower(User.email) == func.lower(username)).one()
            except Exception:
                raise ValueError("Invalid username and/or password")

            try:
                if check_correct_password(user, password, self.bcrypt):
                    # We have a valid login

                    return self.create_session_and_response(session, user)
                else:
                    raise ValueError("Invalid username and/or password")
            except ValueError as ve:
                LoginSession.logout(session)
                raise ve
            except Exception as e:
                LoginSession.logout(session)
                raise e

        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e, StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e, StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e, StatusCode.INTERNAL_ERROR)
예제 #22
0
    def finalize(self):
        """ Set upload job in job tracker database to finished, allowing dependent jobs to be started

        Flask request should include key "upload_id", which holds the job_id for the file_upload job

        Returns:
        A flask response object, if successful just contains key "success" with value True, otherwise value is False
        """
        responseDict = {}
        try:
            inputDictionary = RequestDictionary(self.request)
            jobId = inputDictionary.getValue("upload_id")
            # Compare user ID with user who submitted job, if no match return 400
            job = self.jobManager.getJobById(jobId)
            submission = self.jobManager.getSubmissionForJob(job)
            if(submission.user_id != LoginSession.getName(session)):
                # This user cannot finalize this job
                raise ResponseException("Cannot finalize a job created by a different user", StatusCode.CLIENT_ERROR)
            # Change job status to finished
            if(self.jobManager.checkUploadType(jobId)):
                self.jobManager.changeToFinished(jobId)
                responseDict["success"] = True
                return JsonResponse.create(StatusCode.OK,responseDict)
            else:
                raise ResponseException("Wrong job type for finalize route",StatusCode.CLIENT_ERROR)

        except ( ValueError , TypeError ) as e:
            return JsonResponse.error(e,StatusCode.CLIENT_ERROR)
        except ResponseException as e:
            return JsonResponse.error(e,e.status)
        except Exception as e:
            # Unexpected exception, this is a 500 server error
            return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
예제 #23
0
 def run_instance_function(accountManager,
                           accountFunction,
                           getSystemEmail=False,
                           getSession=False,
                           getUser=False,
                           getCredentials=False):
     """ Standard error handling around each route """
     interfaces = InterfaceHolder()
     try:
         accountManager.addInterfaces(interfaces)
         if (getSystemEmail and getSession):
             return accountFunction(RouteUtils.SYSTEM_EMAIL, session)
         elif (getSystemEmail):
             return accountFunction(RouteUtils.SYSTEM_EMAIL)
         elif (getSession):
             return accountFunction(session)
         elif (getUser):
             if (getCredentials):
                 return accountFunction(LoginSession.getName(session),
                                        RouteUtils.CREATE_CREDENTIALS)
             else:
                 # Currently no functions with user but not credentials flag
                 raise ValueError(
                     "Invalid combination of flags to run_instance_function"
                 )
         else:
             return accountFunction()
     except ResponseException as e:
         return JsonResponse.error(e, e.status)
     except Exception as e:
         exc = ResponseException(str(e), StatusCode.INTERNAL_ERROR, type(e))
         return JsonResponse.error(exc, exc.status)
     finally:
         interfaces.close()
 def run_instance_function(
     accountManager, accountFunction, getSystemEmail=False, getSession=False, getUser=False, getCredentials=False
 ):
     """ Standard error handling around each route """
     interfaces = InterfaceHolder()
     try:
         accountManager.addInterfaces(interfaces)
         if getSystemEmail and getSession:
             return accountFunction(RouteUtils.SYSTEM_EMAIL, session)
         elif getSystemEmail:
             return accountFunction(RouteUtils.SYSTEM_EMAIL)
         elif getSession:
             return accountFunction(session)
         elif getUser:
             if getCredentials:
                 return accountFunction(LoginSession.getName(session), RouteUtils.CREATE_CREDENTIALS)
             else:
                 # Currently no functions with user but not credentials flag
                 raise ValueError("Invalid combination of flags to run_instance_function")
         else:
             return accountFunction()
     except ResponseException as e:
         return JsonResponse.error(e, e.status)
     except Exception as e:
         exc = ResponseException(str(e), StatusCode.INTERNAL_ERROR, type(e))
         return JsonResponse.error(exc, exc.status)
     finally:
         interfaces.close()
예제 #25
0
    def login(self, session):
        """ Logs a user in if their password matches using local data

            Args:
                session: the Session object from flask

            Returns:
                A JsonResponse containing the user information or details on which error occurred, such as whether a
                type was wrong, something wasn't implemented, invalid keys were provided, login was denied, or a
                different, unexpected error occurred.
        """
        try:
            sess = GlobalDB.db().session
            safe_dictionary = RequestDictionary(self.request)

            username = safe_dictionary.get_value('username')
            password = safe_dictionary.get_value('password')

            try:
                user = sess.query(User).filter(
                    func.lower(User.email) == func.lower(username)).one()
            except Exception:
                raise ValueError("Invalid username and/or password")

            try:
                if check_correct_password(user, password, self.bcrypt):
                    # We have a valid login
                    return self.create_session_and_response(session, user)
                else:
                    raise ValueError("Invalid username and/or password")
            except ValueError as ve:
                LoginSession.logout(session)
                raise ve
            except Exception as e:
                LoginSession.logout(session)
                raise e

        # Catch any specifically raised errors or any other errors that may have happened and return them cleanly
        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e, StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e, StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e, StatusCode.INTERNAL_ERROR)
 def listSubmissionsByCurrentUser(self):
     """ List all submission IDs associated with the current user ID """
     userId = LoginSession.getName(flaskSession)
     submissions = self.interfaces.jobDb.getSubmissionsByUserId(userId)
     submissionIdList = []
     for submission in submissions:
         submissionIdList.append(submission.submission_id)
     return JsonResponse.create(StatusCode.OK,{"submission_id_list": submissionIdList})
    def login(self, session):
        """ Logs a user in if their password matches using local data

            Args:
                session: the Session object from flask

            Returns:
                A JsonResponse containing the user information or details on which error occurred, such as whether a
                type was wrong, something wasn't implemented, invalid keys were provided, login was denied, or a
                different, unexpected error occurred.
        """
        try:
            sess = GlobalDB.db().session
            safe_dictionary = RequestDictionary(self.request)

            username = safe_dictionary.get_value('username')
            password = safe_dictionary.get_value('password')

            try:
                user = sess.query(User).filter(func.lower(User.email) == func.lower(username)).one()
            except Exception:
                raise ValueError("Invalid username and/or password")

            try:
                if check_correct_password(user, password, self.bcrypt):
                    # We have a valid login
                    return self.create_session_and_response(session, user)
                else:
                    raise ValueError("Invalid username and/or password")
            except ValueError as ve:
                LoginSession.logout(session)
                raise ve
            except Exception as e:
                LoginSession.logout(session)
                raise e

        # Catch any specifically raised errors or any other errors that may have happened and return them cleanly
        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e, StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e, StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e, StatusCode.INTERNAL_ERROR)
예제 #28
0
 def checkSubmissionPermission(self,submission):
     """ Check if current user has permisson to access submission and return user object. """
     userId = LoginSession.getName(session)
     user = self.interfaces.userDb.getUserByUID(userId)
     # Check that user has permission to see this submission, user must either own the submission or be an admin
     if(submission.user_id != userId and not self.interfaces.userDb.hasPermission(user,"website_admin")):
         raise ResponseException("User does not have permission to view that submission",StatusCode.CLIENT_ERROR)
     return user
    def check_email_confirmation_token(self,session):
        """

        Creates user record and email

        arguments:

        session -- (Session) object from flask

        return the response object with a error code and a message

        """
        sess = GlobalDB.db().session
        request_fields = RequestDictionary.derive(self.request)
        try:
            if 'token' not in request_fields:
                raise ResponseException(
                    "Request body must include token",
                    StatusCode.CLIENT_ERROR
                )
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        token = request_fields['token']
        session["token"] = token
        success, message, errorCode = sesEmail.check_token(token, "validate_email")
        if success:
            #mark session that email can be filled out
            LoginSession.register(session)

            #remove token so it cant be used again
            # The following lines are commented out for issues with registration email links bouncing users back
            # to the original email input page instead of the registration page
            # oldToken = sess.query(EmailToken).filter(EmailToken.token == session["token"]).one()
            # sess.delete(oldToken)
            # sess.commit()

            #set the status only if current status is awaiting confirmation
            user = sess.query(User).filter(func.lower(User.email) == func.lower(message)).one()
            if user.user_status_id == USER_STATUS_DICT["awaiting_confirmation"]:
                user.user_status_id = USER_STATUS_DICT["email_confirmed"]
                sess.commit()
            return JsonResponse.create(StatusCode.OK,{"email":message,"errorCode":errorCode,"message":"success"})
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK,{"errorCode":errorCode,"message":message})
예제 #30
0
    def checkEmailConfirmationToken(self, session):
        """

        Creates user record and email

        arguments:

        session -- (Session) object from flask

        return the reponse object with a error code and a message

        """
        requestFields = RequestDictionary(self.request)
        if (not requestFields.exists("token")):
            exc = ResponseException("Request body must include token",
                                    StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc, exc.status)
        token = requestFields.getValue("token")
        session["token"] = token
        success, message, errorCode = sesEmail.checkToken(
            token, self.interfaces.userDb, "validate_email")
        if (success):
            #mark session that email can be filled out
            LoginSession.register(session)

            #remove token so it cant be used again
            # The following line is commented out for issues with registration email links bouncing users back
            # to the original email input page instead of the registration page
            #self.interfaces.userDb.deleteToken(token)

            #set the status only if current status is awaiting confirmation
            user = self.interfaces.userDb.getUserByEmail(message)
            if self.interfaces.userDb.checkStatus(user,
                                                  "awaiting_confirmation"):
                self.interfaces.userDb.changeStatus(user, "email_confirmed")
            return JsonResponse.create(StatusCode.OK, {
                "email": message,
                "errorCode": errorCode,
                "message": "success"
            })
        else:
            #failure but alert UI of issue
            return JsonResponse.create(StatusCode.OK, {
                "errorCode": errorCode,
                "message": message
            })
예제 #31
0
 def submit_files():
     fileManager = FileHandler(request,
                               isLocal=IS_LOCAL,
                               serverPath=SERVER_PATH)
     return RouteUtils.run_instance_function(fileManager,
                                             fileManager.submit,
                                             LoginSession.getName(session),
                                             RouteUtils.CREATE_CREDENTIALS)
예제 #32
0
    def resetPassword(self, system_email, session):
        """

        Remove old password and email user a token to set a new password.  Request should have key "email"

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask

        """
        requestDict = RequestDictionary(self.request)
        if (not (requestDict.exists("email"))):
            # Don't have the keys we need in request
            exc = ResponseException(
                "Reset password route requires key 'email'",
                StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc, exc.status)
        # Get user object
        try:
            user = self.interfaces.userDb.getUserByEmail(
                requestDict.getValue("email"))
        except Exception as e:
            exc = ResponseException("Unknown Error", StatusCode.CLIENT_ERROR,
                                    ValueError)
            return JsonResponse.error(exc, exc.status)

        LoginSession.logout(session)
        self.interfaces.userDb.session.commit()
        email = requestDict.getValue("email")
        # Send email with token
        emailToken = sesEmail.createToken(email, self.interfaces.userDb,
                                          "password_reset")
        link = "".join(
            [AccountHandler.FRONT_END, '#/forgotpassword/', emailToken])
        emailTemplate = {'[URL]': link}
        newEmail = sesEmail(user.email,
                            system_email,
                            templateType="reset_password",
                            parameters=emailTemplate,
                            database=self.interfaces.userDb)
        newEmail.send()
        # Return success message
        return JsonResponse.create(StatusCode.OK,
                                   {"message": "Password reset"})
예제 #33
0
    def startGenerationJob(self, submission_id, file_type):
        """ Initiates a file generation job

        Args:
            submission_id: ID of submission to start job for
            file_type: Type of file to be generated

        Returns:
            Tuple of boolean indicating successful start, and error response if False

        """
        jobDb = self.interfaces.jobDb
        file_type_name = self.fileTypeMap[file_type]

        if file_type in ["D1", "D2"]:
            # Populate start and end dates, these should be provided in MM/DD/YYYY format, using calendar year (not fiscal year)
            requestDict = RequestDictionary(self.request)
            start_date = requestDict.getValue("start")
            end_date = requestDict.getValue("end")

            if not (StringCleaner.isDate(start_date) and StringCleaner.isDate(end_date)):
                exc = ResponseException("Start or end date cannot be parsed into a date", StatusCode.CLIENT_ERROR)
                return False, JsonResponse.error(exc, exc.status, start = "", end = "", file_type = file_type, status = "failed")
        elif file_type not in ["E","F"]:
            exc = ResponseException("File type must be either D1, D2, E or F", StatusCode.CLIENT_ERROR)
            return False, JsonResponse.error(exc, exc.status, file_type = file_type, status = "failed")

        cgac_code = self.jobManager.getSubmissionById(submission_id).cgac_code

        # Generate and upload file to S3
        user_id = LoginSession.getName(session)
        timestamped_name = s3UrlHandler.getTimestampedFilename(CONFIG_BROKER["".join([str(file_type_name),"_file_name"])])
        if self.isLocal:
            upload_file_name = "".join([CONFIG_BROKER['broker_files'], timestamped_name])
        else:
            upload_file_name = "".join([str(user_id), "/", timestamped_name])

        job = jobDb.getJobBySubmissionFileTypeAndJobType(submission_id, file_type_name, "file_upload")
        job.filename = upload_file_name
        job.original_filename = timestamped_name
        job.job_status_id = jobDb.getJobStatusId("running")
        jobDb.session.commit()
        if file_type in ["D1", "D2"]:
            CloudLogger.log("DEBUG: Adding job info for job id of " + str(job.job_id),
                            log_type="debug",
                            file_name=self.debug_file_name)
            return self.addJobInfoForDFile(upload_file_name, timestamped_name, submission_id, file_type, file_type_name, start_date, end_date, cgac_code, job)
        elif file_type == 'E':
            generate_e_file.delay(
                submission_id, job.job_id, InterfaceHolder, timestamped_name,
                upload_file_name, self.isLocal)
        elif file_type == 'F':
            generate_f_file.delay(
                submission_id, job.job_id, InterfaceHolder, timestamped_name,
                upload_file_name, self.isLocal)

        return True, None
예제 #34
0
 def listSubmissionsByCurrentUser(self):
     """ List all submission IDs associated with the current user ID """
     userId = LoginSession.getName(flaskSession)
     submissions = self.interfaces.jobDb.getSubmissionsByUserId(userId)
     submissionIdList = []
     for submission in submissions:
         submissionIdList.append(submission.submission_id)
     return JsonResponse.create(StatusCode.OK,
                                {"submission_id_list": submissionIdList})
예제 #35
0
        def decorated_function(*args, **kwargs):
            try:
                errorMessage  = "Login Required"
                if "check_email_token" in permissionList:
                    if(LoginSession.isRegistering(session)) :
                        return f(*args, **kwargs)
                    else :
                        errorMessage  = "unauthorized"
                elif "check_password_token" in permissionList  :
                    if(LoginSession.isResetingPassword(session)) :
                        return f(*args, **kwargs)
                    else :
                        errorMessage  = "unauthorized"
                elif LoginSession.isLogin(session):
                    userDb = UserHandler()
                    try:
                        user = userDb.getUserByUID(session["name"])
                        validUser = True
                        for permission in permissionList :
                            if(not userDb.hasPermission(user, permission)) :
                                validUser = False
                            else:
                                validUser = True
                                break

                    finally:
                        userDb.close()
                    if(validUser) :
                        return f(*args, **kwargs)
                    errorMessage  = "Wrong User Type"

                returnResponse = flask.Response()
                returnResponse.headers["Content-Type"] = "application/json"
                returnResponse.status_code = 401 # Error code
                responseDict = {}
                responseDict["message"] = errorMessage
                returnResponse.set_data(json.dumps(responseDict))
                return returnResponse

            except ResponseException as e:
                return JsonResponse.error(e,e.status)
            except Exception as e:
                exc = ResponseException(str(e),StatusCode.INTERNAL_ERROR,type(e))
                return JsonResponse.error(exc,exc.status)
예제 #36
0
 def create_session_and_response(self, session, user):
     # Create session
     LoginSession.login(session, user.user_id)
     permissionList = []
     for permission in self.interfaces.userDb.getPermissionList():
         if (self.interfaces.userDb.hasPermission(user, permission.name)):
             permissionList.append(permission.permission_type_id)
     self.interfaces.userDb.updateLastLogin(user)
     agency_name = self.interfaces.validationDb.getAgencyName(
         user.cgac_code)
     return JsonResponse.create(
         StatusCode.OK, {
             "message": "Login successful",
             "user_id": int(user.user_id),
             "name": user.name,
             "title": user.title,
             "agency_name": agency_name,
             "cgac_code": user.cgac_code,
             "permissions": permissionList
         })
    def listAgencies(self):
        """ Retrieves a list of all agency names and their cgac codes. If there is
         a user logged in, it will check if that user is part of the 'SYS' agency.
         If so, 'SYS' will be added to the agency_list. """
        agencies = self.validationManager.getAllAgencies()
        agency_list = []

        for agency in agencies:
            agency_list.append({
                "agency_name": agency.agency_name,
                "cgac_code": agency.cgac_code
            })

        if LoginSession.isLogin(session):
            user_id = LoginSession.getName(session)
            user = self.userManager.getUserByUID(user_id)
            if user.cgac_code.lower() == "sys":
                agency_list.append({"agency_name": "SYS", "cgac_code": "SYS"})

        return JsonResponse.create(StatusCode.OK,
                                   {"cgac_agency_list": agency_list})
예제 #38
0
    def checkSubmissionPermission(self,submission):
        """ Check if current user has permisson to access submission and return user object.

        Args:
            submission - Submission model object
        """
        userId = LoginSession.getName(session)
        user = self.interfaces.userDb.getUserByUID(userId)
        # Check that user has permission to see this submission, user must be within the agency of the submission
        if(submission.cgac_code != user.cgac_code and submission.user_id != user.user_id):
            raise ResponseException("User does not have permission to view that submission",StatusCode.CLIENT_ERROR)
        return user
    def list_agencies(self):
        """ Retrieves a list of all agency names and their cgac codes. If there is
         a user logged in, it will check if that user is part of the 'SYS' agency.
         If so, 'SYS' will be added to the agency_list. """
        sess = GlobalDB.db().session
        agencies = sess.query(CGAC).all()
        agency_list = []

        for agency in agencies:
            agency_list.append({
                "agency_name": agency.agency_name,
                "cgac_code": agency.cgac_code
            })

        if LoginSession.isLogin(session):
            user = sess.query(User).filter(
                User.user_id == LoginSession.getName(session)).one()
            if user.cgac_code.lower() == "sys":
                agency_list.append({"agency_name": "SYS", "cgac_code": "SYS"})

        return JsonResponse.create(StatusCode.OK,
                                   {"cgac_agency_list": agency_list})
 def list_user_emails(self):
     """ List user names and emails """
     sess = GlobalDB.db().session
     user = sess.query(User).filter(User.user_id == LoginSession.getName(flaskSession)).one()
     try:
         users = sess.query(User).filter(User.cgac_code == user.cgac_code, User.user_status_id == USER_STATUS_DICT["approved"], User.is_active == True).all()
     except ValueError as exc:
         # Client provided a bad status
         return JsonResponse.error(exc, StatusCode.CLIENT_ERROR)
     user_info = []
     for user in users:
         this_info = {"id":user.user_id, "name": user.name, "email": user.email}
         user_info.append(this_info)
     return JsonResponse.create(StatusCode.OK, {"users": user_info})
예제 #41
0
    def listUsers(self):
        """ List all users ordered by status. Associated request body must have key 'filter_by' """
        requestDict = RequestDictionary(self.request, optionalRequest=True)
        user_status = requestDict.getValue("status") if requestDict.exists(
            "status") else "all"

        user = self.interfaces.userDb.getUserByUID(
            LoginSession.getName(flaskSession))
        isAgencyAdmin = self.userManager.hasPermission(
            user, "agency_admin") and not self.userManager.hasPermission(
                user, "website_admin")
        try:
            if isAgencyAdmin:
                users = self.interfaces.userDb.getUsers(
                    cgac_code=user.cgac_code, status=user_status)
            else:
                users = self.interfaces.userDb.getUsers(status=user_status)
        except ValueError as e:
            # Client provided a bad status
            exc = ResponseException(str(e), StatusCode.CLIENT_ERROR,
                                    ValueError)
            return JsonResponse.error(exc, exc.status)
        userInfo = []
        for user in users:
            agency_name = self.interfaces.validationDb.getAgencyName(
                user.cgac_code)
            thisInfo = {
                "name":
                user.name,
                "title":
                user.title,
                "agency_name":
                agency_name,
                "cgac_code":
                user.cgac_code,
                "email":
                user.email,
                "id":
                user.user_id,
                "is_active":
                user.is_active,
                "permissions":
                ",".join(self.interfaces.userDb.getUserPermissions(user)),
                "status":
                user.user_status.name
            }
            userInfo.append(thisInfo)
        return JsonResponse.create(StatusCode.OK, {"users": userInfo})
예제 #42
0
    def checkSubmissionPermission(self,submission):
        """ Check if current user has permisson to access submission and return user object.

        Args:
            submission - Submission model object
        """
        userId = LoginSession.getName(session)
        user = self.interfaces.userDb.getUserByUID(userId)
        # Check that user has permission to see this submission, user must be within the agency of the submission, or be
        # the original user, or be in the 'SYS' agency
        submissionCgac = StringCleaner.cleanString(submission.cgac_code)
        userCgac = StringCleaner.cleanString(user.cgac_code)
        if(submissionCgac != userCgac and submission.user_id != user.user_id
           and userCgac != "sys"):
            raise ResponseException("User does not have permission to view that submission",
                StatusCode.PERMISSION_DENIED)
        return user
예제 #43
0
    def listSubmissionsByCurrentUserAgency(self):
        """ List all submission IDs associated with the current user's agency """
        userId = LoginSession.getName(flaskSession)
        user = self.interfaces.userDb.getUserByUID(userId)
        submissions = self.interfaces.jobDb.getSubmissionsByUserAgency(user)
        submissionDetails = []
        for submission in submissions:
            jobIds = self.interfaces.jobDb.getJobsBySubmission(
                submission.submission_id)
            total_size = 0
            for jobId in jobIds:
                file_size = self.interfaces.jobDb.getFileSize(jobId)
                total_size += file_size if file_size is not None else 0

            status = self.interfaces.jobDb.getSubmissionStatus(
                submission.submission_id, self.interfaces)
            error_count = self.interfaces.errorDb.sumNumberOfErrorsForJobList(
                jobIds, self.interfaces.validationDb)
            if submission.user_id is None:
                submission_user_name = "No user"
            else:
                submission_user_name = self.interfaces.userDb.getUserByUID(
                    submission.user_id).name
            submissionDetails.append({
                "submission_id":
                submission.submission_id,
                "last_modified":
                submission.updated_at.strftime('%m/%d/%Y'),
                "size":
                total_size,
                "status":
                status,
                "errors":
                error_count,
                "reporting_start_date":
                str(submission.reporting_start_date),
                "reporting_end_date":
                str(submission.reporting_end_date),
                "user": {
                    "user_id": submission.user_id,
                    "name": submission_user_name
                }
            })
        return JsonResponse.create(StatusCode.OK,
                                   {"submissions": submissionDetails})
    def listSubmissionsByCurrentUser(self):
        """ List all submission IDs associated with the current user ID """
        userId = LoginSession.getName(flaskSession)
        user = self.interfaces.userDb.getUserByUID(userId)
        submissions = self.interfaces.jobDb.getSubmissionsByUserId(userId)
        submissionDetails = []
        for submission in submissions:
            jobIds = self.interfaces.jobDb.getJobsBySubmission(submission.submission_id)
            total_size = 0
            for jobId in jobIds:
                file_size = self.interfaces.jobDb.getFileSize(jobId)
                total_size += file_size if file_size is not None else 0

            status = self.interfaces.jobDb.getSubmissionStatus(submission.submission_id)
            error_count = self.interfaces.errorDb.sumNumberOfErrorsForJobList(jobIds)
            submissionDetails.append(
                {"submission_id": submission.submission_id, "last_modified": submission.updated_at.strftime('%m/%d/%Y'),
                 "size": total_size, "status": status, "errors": error_count, "reporting_start_date": str(submission.reporting_start_date),
                                      "reporting_end_date": str(submission.reporting_end_date), "user": {"user_id": str(userId),
                                                                                                    "name": user.name}})
        return JsonResponse.create(StatusCode.OK, {"submissions": submissionDetails})
 def listUsers(self):
     """ List all users ordered by status. Associated request body must have key 'filter_by' """
     user = self.interfaces.userDb.getUserByUID(LoginSession.getName(flaskSession))
     isAgencyAdmin = True if self.interfaces.userDb.hasPermission(user, "agency_admin") else False
     try:
         if isAgencyAdmin:
             users = self.interfaces.userDb.getUsers(cgac_code=user.cgac_code)
         else:
             users = self.interfaces.userDb.getUsers()
     except ValueError as e:
         # Client provided a bad status
         exc = ResponseException(str(e),StatusCode.CLIENT_ERROR,ValueError)
         return JsonResponse.error(exc,exc.status)
     userInfo = []
     for user in users:
         agency_name = self.interfaces.validationDb.getAgencyName(user.cgac_code)
         thisInfo = {"name":user.name, "title":user.title, "agency_name":agency_name, "cgac_code":user.cgac_code,
                     "email":user.email, "id":user.user_id, "is_active":user.is_active,
                     "permissions": ",".join(self.interfaces.userDb.getUserPermissions(user)), "status": user.user_status.name}
         userInfo.append(thisInfo)
     return JsonResponse.create(StatusCode.OK,{"users":userInfo})
예제 #46
0
 def sessionCheck():
     session["session_check"] = True
     return JsonResponse.create(StatusCode.OK,{"status":str(LoginSession.isLogin(session))})
    def login(self,session):
        """

        Logs a user in if their password matches

        arguments:

        session  -- (Session) object from flask

        return the reponse object

        """
        try:
            safeDictionary = RequestDictionary(self.request)

            username = safeDictionary.getValue('username')

            password = safeDictionary.getValue('password')

            try:
                user = self.interfaces.userDb.getUserByEmail(username)
            except Exception as e:
                raise ValueError("Invalid username and/or password")

            if(not self.interfaces.userDb.checkStatus(user,"approved")):
                raise ValueError("Invalid username and/or password")

            # Only check if user is active after they've logged in for the first time
            if user.last_login_date is not None and self.isAccountExpired(user):
                raise ValueError("Your account has expired. Please contact an administrator.")

            # for whatever reason, your account is not active, therefore it's locked
            if not self.isUserActive(user):
                raise ValueError("Your account has been locked. Please contact an administrator.")

            try:
                if(self.interfaces.userDb.checkPassword(user,password,self.bcrypt)):
                    # We have a valid login

                    # Reset incorrect password attempt count to 0
                    self.resetPasswordCount(user)

                    LoginSession.login(session,user.user_id)
                    permissionList = []
                    for permission in self.interfaces.userDb.getPermissionList():
                        if(self.interfaces.userDb.hasPermission(user, permission.name)):
                            permissionList.append(permission.permission_type_id)
                    self.interfaces.userDb.updateLastLogin(user)
                    agency_name = self.interfaces.validationDb.getAgencyName(user.cgac_code)
                    return JsonResponse.create(StatusCode.OK,{"message":"Login successful","user_id": int(user.user_id),
                                                              "name":user.name,"title":user.title,"agency_name":agency_name,
                                                              "cgac_code":user.cgac_code, "permissions" : permissionList})
                else :
                    # increase incorrect password attempt count by 1
                    # if this is the 3rd incorrect attempt, lock account
                    self.incrementPasswordCount(user)
                    if user.incorrect_password_attempts == 3:
                        raise ValueError("Your account has been locked due to too many failed login attempts. Please contact an administrator.")

                    raise ValueError("Invalid username and/or password")
            except ValueError as ve:
                LoginSession.logout(session)
                raise ve
            except Exception as e:
                LoginSession.logout(session)
                raise ValueError("Invalid username and/or password")

        except (TypeError, KeyError, NotImplementedError) as e:
            # Return a 400 with appropriate message
            return JsonResponse.error(e,StatusCode.CLIENT_ERROR)
        except ValueError as e:
            # Return a 401 for login denied
            return JsonResponse.error(e,StatusCode.LOGIN_REQUIRED)
        except Exception as e:
            # Return 500
            return JsonResponse.error(e,StatusCode.INTERNAL_ERROR)
        return self.response
 def create_session_and_response(session, user):
     """Create a session."""
     LoginSession.login(session, user.user_id)
     data = json_for_user(user)
     data['message'] = 'Login successful'
     return JsonResponse.create(StatusCode.OK, data)
    def register(self,system_email,session):
        """

        Save user's information into user database.  Associated request body should have keys 'email', 'name', 'agency', and 'title'

        arguments:

        system_email  -- (string) email used to send messages
        session  -- (Session) object from flask


        Returns message that registration is successful or error message that fields are not valid

        """
        def ThreadedFunction (from_email="",username="",title="",agency="",userEmail="" ,link="") :
            """
            This inner function sends emails in a new thread as there could be lots of admins

            from_email -- (string) the from email address
            username -- (string) the name of the  user
            title  --   (string) the title of the  user
            agency -- (string) the agency of the  user
            userEmail -- (string) the email of the user
            link  -- (string) the broker email link
            """
            threadedDatabase =  UserHandler()
            try:
                for user in threadedDatabase.getUsersByType("website_admin") :
                    emailTemplate = {'[REG_NAME]': username, '[REG_TITLE]':title, '[REG_AGENCY]':agency,'[REG_EMAIL]' : userEmail,'[URL]':link}
                    newEmail = sesEmail(user.email, system_email,templateType="account_creation",parameters=emailTemplate,database=threadedDatabase)
                    newEmail.send()
            finally:
                InterfaceHolder.closeOne(threadedDatabase)

        requestFields = RequestDictionary(self.request)
        if(not (requestFields.exists("email") and requestFields.exists("name") and requestFields.exists("agency") and requestFields.exists("title") and requestFields.exists("password"))):
            # Missing a required field, return 400
            exc = ResponseException("Request body must include email, name, agency, title, and password", StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)

        if(not self.checkPassword(requestFields.getValue("password"))):
            exc = ResponseException("Invalid Password", StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        # Find user that matches specified email
        user = self.interfaces.userDb.getUserByEmail(requestFields.getValue("email"))
        # Check that user's status is before submission of registration
        if not (self.interfaces.userDb.checkStatus(user,"awaiting_confirmation") or self.interfaces.userDb.checkStatus(user,"email_confirmed")):
            # Do not allow duplicate registrations
            exc = ResponseException("User already registered",StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc,exc.status)
        # Add user info to database
        self.interfaces.userDb.addUserInfo(user,requestFields.getValue("name"),requestFields.getValue("agency"),requestFields.getValue("title"))
        self.interfaces.userDb.setPassword(user,requestFields.getValue("password"),self.bcrypt)

        userLink= "".join([AccountHandler.FRONT_END, '#/login?redirect=/admin'])
        # Send email to approver list
        emailThread = Thread(target=ThreadedFunction, kwargs=dict(from_email=system_email,username=user.name,title=user.title,agency=user.agency,userEmail=user.email,link=userLink))
        emailThread.start()

        #email user
        link= AccountHandler.FRONT_END
        emailTemplate = {'[EMAIL]' : system_email}
        newEmail = sesEmail(user.email, system_email,templateType="account_creation_user",parameters=emailTemplate,database=self.interfaces.userDb)
        newEmail.send()

        LoginSession.logout(session)
        # Mark user as awaiting approval
        self.interfaces.userDb.changeStatus(user,"awaiting_approval")
        return JsonResponse.create(StatusCode.OK,{"message":"Registration successful"})