Exemplo n.º 1
0
        def wrapped(*args, **kwargs):
            sess = GlobalDB.db().session
            try:
                req_args = {
                    'agency_code':
                    RequestDictionary.derive(request).get('agency_code', None),
                    'existing_submission_id':
                    RequestDictionary.derive(request).get(
                        'existing_submission_id', None)
                }
            except (ValueError, TypeError) as e:
                raise ResponseException(e, StatusCode.CLIENT_ERROR)
            except BadRequest:
                raise ResponseException(
                    'Bad request: agency_code or existing_submission_id not included properly',
                    StatusCode.CLIENT_ERROR)

            if req_args['agency_code'] is None and req_args[
                    'existing_submission_id'] is None:
                raise ResponseException(
                    'Missing required parameter: agency_code or existing_submission_id',
                    StatusCode.CLIENT_ERROR)
            if not isinstance(req_args['agency_code'], str) and not isinstance(
                    req_args['existing_submission_id'], str):
                raise ResponseException(
                    'Bad request: agency_code or existing_submission_id' +
                    'required and must be strings', StatusCode.CLIENT_ERROR)
            if req_args['existing_submission_id'] is not None:
                check_existing_submission_perms(
                    perm, req_args['existing_submission_id'])
            else:
                sub_tier_agency = sess.query(SubTierAgency).\
                    filter(SubTierAgency.sub_tier_agency_code == req_args['agency_code']).one_or_none()

                if sub_tier_agency is None:
                    raise ResponseException(
                        'sub_tier_agency must be a valid sub_tier_agency_code',
                        StatusCode.CLIENT_ERROR)

                cgac_code = sub_tier_agency.cgac.cgac_code if sub_tier_agency.cgac_id else None
                frec_code = sub_tier_agency.frec.frec_code if sub_tier_agency.frec_id else None
                if not active_user_can(
                        perm, cgac_code=cgac_code, frec_code=frec_code):
                    raise ResponseException(
                        "User does not have permissions to write to that subtier agency",
                        StatusCode.PERMISSION_DENIED)

            return fn(*args, **kwargs)
    def list_users_with_status(self):
        """ List all users with the specified status.  Associated request body must have key 'status' """
        request_dict = RequestDictionary.derive(self.request)
        try:
            if 'status' not in request_dict:
                # Missing a required field, return 400
                raise ResponseException(
                    "Request body must include status", StatusCode.CLIENT_ERROR)
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        sess = GlobalDB.db().session

        try:
            users = sess.query(User).filter_by(
                user_status_id=USER_STATUS_DICT[request_dict['status']]
            ).all()
        except ValueError as exc:
            # Client provided a bad status
            return JsonResponse.error(exc, StatusCode.CLIENT_ERROR)
        user_info = []
        for user in users:
            agency_name = sess.query(CGAC.agency_name).\
                filter(CGAC.cgac_code == user.cgac_code).\
                one_or_none()
            this_info = {"name":user.name, "title":user.title, "agency_name":agency_name, "cgac_code":user.cgac_code,
                        "email":user.email, "id":user.user_id }
            user_info.append(this_info)
        return JsonResponse.create(StatusCode.OK,{"users":user_info})
    def email_users(self, system_email):
        """ Send email notification to list of users

            Args:
                system_email: the address of the system to send the email from

            Returns:
                A JsonReponse containing a message that the email sent successfully or the details of the missing
                parameters
        """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        required = ('users', 'submission_id', 'email_template')
        try:
            if any(field not in request_dict for field in required):
                raise ResponseException(
                    "Email users route requires users, email_template, and submission_id",
                    StatusCode.CLIENT_ERROR)
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        user_ids = request_dict['users']
        submission_id = request_dict['submission_id']
        # Check if submission id is valid
        _, agency_name = sess.query(Submission.submission_id, CGAC.agency_name).\
            join(CGAC, Submission.cgac_code == CGAC.cgac_code).filter(Submission.submission_id == submission_id).one()
        if not agency_name:
            _, agency_name = sess.query(Submission.submission_id, FREC.agency_name).\
                join(FREC, Submission.frec_code == FREC.frec_code).\
                filter(Submission.submission_id == submission_id).one()

        template_type = request_dict['email_template']
        # Check if email template type is valid
        get_email_template(template_type)

        users = []

        link = "".join(
            [AccountHandler.FRONT_END, '#/reviewData/',
             str(submission_id)])
        email_template = {
            '[REV_USER_NAME]': g.user.name,
            '[REV_AGENCY]': agency_name,
            '[REV_URL]': link
        }

        for user_id in user_ids:
            # Check if user id is valid, if so add User object to array
            users.append(
                sess.query(User).filter(User.user_id == user_id).one())

        for user in users:
            new_email = SesEmail(user.email,
                                 system_email,
                                 template_type=template_type,
                                 parameters=email_template)
            new_email.send()

        return JsonResponse.create(StatusCode.OK,
                                   {"message": "Emails successfully sent"})
    def set_skip_guide(self):
        """ Set current user's skip guide parameter

            Returns:
                JsonResponse object containing results of setting the skip guide or details of the error that occurred.
                Possible errors include the request not containing a skip_guide parameter or it not being a boolean
                value
        """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        try:
            if 'skip_guide' not in request_dict:
                raise ResponseException(
                    "Must include skip_guide parameter",
                    StatusCode.CLIENT_ERROR
                )
            skip_guide = str(request_dict['skip_guide']).lower()
            if skip_guide not in ("true", "false"):
                raise ResponseException(
                    "skip_guide must be true or false",
                    StatusCode.CLIENT_ERROR
                )
            g.user.skip_guide = skip_guide == "true"
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)
        sess.commit()
        return JsonResponse.create(StatusCode.OK, {"message": "skip_guide set successfully", "skip_guide": skip_guide})
    def list_users(self):
        """ List all users ordered by status. Associated request body must have key 'filter_by' """
        request_dict = RequestDictionary.derive(
            self.request, optional_request=True)
        user_status = request_dict.get('status', 'all')
        sess = GlobalDB.db().session
        try:
            user_query = sess.query(User)
            if user_status != "all":
                user_query = user_query.filter(User.user_status_id == USER_STATUS_DICT[user_status])
            users = user_query.all()
        except ValueError as exc:
            # Client provided a bad status
            return JsonResponse.error(exc, StatusCode.CLIENT_ERROR)
        user_info = []
        for user in users:
            agency_name = sess.query(CGAC.agency_name).\
                filter(CGAC.cgac_code == user.cgac_code).\
                one_or_none()

            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,
                        "permission": PERMISSION_TYPE_DICT_ID.get(user.permission_type_id), "status": user.user_status.name}
            user_info.append(thisInfo)
        return JsonResponse.create(StatusCode.OK,{"users":user_info})
    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"})
 def upload_fabs_file():
     if "multipart/form-data" not in request.headers['Content-Type']:
         return JsonResponse.error(ValueError("Request must be a multipart/form-data type"), StatusCode.CLIENT_ERROR)
     params = RequestDictionary.derive(request)
     fabs = params.get('_files', {}).get('fabs', None)
     file_manager = FileHandler(request, is_local=is_local, server_path=server_path)
     return file_manager.upload_fabs_file(fabs)
    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 set_skip_guide(self):
        """ Set current user's skip guide parameter

            Returns:
                JsonResponse object containing results of setting the skip guide or details of the error that occurred.
                Possible errors include the request not containing a skip_guide parameter or it not being a boolean
                value
        """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        try:
            if 'skip_guide' not in request_dict:
                raise ResponseException("Must include skip_guide parameter",
                                        StatusCode.CLIENT_ERROR)
            skip_guide = str(request_dict['skip_guide']).lower()
            if skip_guide not in ("true", "false"):
                raise ResponseException("skip_guide must be true or false",
                                        StatusCode.CLIENT_ERROR)
            g.user.skip_guide = skip_guide == "true"
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)
        sess.commit()
        return JsonResponse.create(StatusCode.OK, {
            "message": "skip_guide set successfully",
            "skip_guide": skip_guide
        })
 def upload_fabs_file():
     if "multipart/form-data" not in request.headers['Content-Type']:
         return JsonResponse.error(ValueError("Request must be a multipart/form-data type"), StatusCode.CLIENT_ERROR)
     params = RequestDictionary.derive(request)
     fabs = params.get('_files', {}).get('fabs', None)
     file_manager = FileHandler(request, is_local=is_local, server_path=server_path)
     return file_manager.upload_fabs_file(fabs)
    def set_new_password(self, session):
        """ Set a new password for a user, request should have keys "user_email" and "password" """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        required = ('user_email', 'password')
        try:
            if any(field not in request_dict for field in required):
                # Don't have the keys we need in request
                raise ResponseException(
                    "Set password route requires keys user_email and password",
                    StatusCode.CLIENT_ERROR
                )
            if not self.checkPassword(request_dict['password']):
                raise ResponseException(
                    "Invalid Password", StatusCode.CLIENT_ERROR)
        except ResponseException as exc:
            return JsonResponse.error(exc,exc.status)

        # Get user from email
        user = sess.query(User).filter(
            func.lower(User.email) == func.lower(request_dict["user_email"])
        ).one()
        # Set new password
        set_user_password(user,request_dict["password"],self.bcrypt)
        # Invalidate token
        oldToken = sess.query(EmailToken).filter(EmailToken.token == session["token"]).one()
        sess.delete(oldToken)
        sess.commit()
        session["reset"] = None
        # Return success message
        return JsonResponse.create(StatusCode.OK,{"message":"Password successfully changed"})
        def wrapped(*args, **kwargs):
            sess = GlobalDB.db().session
            try:
                req_args = {
                    'agency_code': RequestDictionary.derive(request).get('agency_code', None),
                    'existing_submission_id': RequestDictionary.derive(request).get('existing_submission_id', None)
                    }
            except (ValueError, TypeError) as e:
                raise ResponseException(e, StatusCode.CLIENT_ERROR)
            except BadRequest as e:
                raise ResponseException('Bad request: agency_code or existing_submission_id not included properly',
                                        StatusCode.CLIENT_ERROR)

            if req_args['agency_code'] is None and req_args['existing_submission_id'] is None:
                raise ResponseException('Missing required parameter: agency_code or existing_submission_id',
                                        StatusCode.CLIENT_ERROR)
            if not isinstance(req_args['agency_code'], str) and not isinstance(req_args['existing_submission_id'], str):
                raise ResponseException('Bad request: agency_code or existing_submission_id' +
                                        'required and must be strings', StatusCode.CLIENT_ERROR)
            if req_args['existing_submission_id'] is not None:
                check_existing_submission_perms(perm, req_args['existing_submission_id'])
            else:
                sub_tier_agency = sess.query(SubTierAgency).\
                    filter(SubTierAgency.sub_tier_agency_code == req_args['agency_code']).one_or_none()

                if sub_tier_agency is None:
                    raise ResponseException('sub_tier_agency must be a valid sub_tier_agency_code',
                                            StatusCode.CLIENT_ERROR)

                cgac_code = sub_tier_agency.cgac.cgac_code if sub_tier_agency.cgac_id else None
                frec_code = sub_tier_agency.frec.frec_code if sub_tier_agency.frec_id else None
                if not current_user_can(perm, cgac_code=cgac_code, frec_code=frec_code):
                    raise ResponseException("User does not have permissions to write to that subtier agency",
                                            StatusCode.PERMISSION_DENIED)

            return fn(*args, **kwargs)
    def create_email_confirmation(self,system_email):
        """

        Creates user record and email

        arguments:

        system_email  -- (string) email used to send messages

        """
        sess = GlobalDB.db().session
        request_fields = RequestDictionary.derive(self.request)
        try:
            if 'email' not in request_fields:
                raise ResponseException(
                    "Request body must include email", StatusCode.CLIENT_ERROR)
            email = request_fields['email']
            if not re.match("[^@]+@[^@]+\.[^@]+",email):
                raise ValueError("Invalid Email Format")
        except (ResponseException, ValueError) as exc:
            return JsonResponse.error(exc, StatusCode.CLIENT_ERROR)

        try :
            user = sess.query(User).filter(
                func.lower(User.email) == func.lower(request_fields['email'])
            ).one()
        except NoResultFound:
            # Create user with specified email if none is found
            user = User(email=email)
            user.user_status_id = USER_STATUS_DICT["awaiting_confirmation"]
            user.permissions = 0
            sess.add(user)
            sess.commit()
        else:
            try:
                good_statuses = (USER_STATUS_DICT["awaiting_confirmation"],
                                 USER_STATUS_DICT["email_confirmed"])
                if user.user_status_id not in good_statuses:
                    raise ResponseException(
                        "User already registered", StatusCode.CLIENT_ERROR)
            except ResponseException as exc:
                return JsonResponse.error(exc, exc.status)
        email_token = sesEmail.createToken(email, "validate_email")
        link= "".join([AccountHandler.FRONT_END,'#/registration/',email_token])
        email_template = {'[USER]': email, '[URL]':link}
        new_email = sesEmail(email, system_email,templateType="validate_email",parameters=email_template)
        new_email.send()
        return JsonResponse.create(StatusCode.OK,{"message":"Email Sent"})
 def deleteUser(self):
     """ Deletes user specified by 'email' in request """
     sess = GlobalDB.db().session
     request_dict = RequestDictionary.derive(self.request)
     try:
         if 'email' not in request_dict:
             # missing required fields, return 400
             raise ResponseException(
                 "Request body must include email of user to be deleted",
                 StatusCode.CLIENT_ERROR
             )
     except ResponseException as exc:
         return JsonResponse.error(exc, exc.status)
     email = request_dict['email']
     sess.query(User).filter(User.email == email).delete()
     sess.commit()
     return JsonResponse.create(StatusCode.OK,{"message":"success"})
    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})
    def email_users(self, system_email):
        """ Send email notification to list of users """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        required = ('users', 'submission_id', 'email_template')
        try:
            if any(field not in request_dict for field in required):
                raise ResponseException(
                    "Email users route requires users, email_template, and "
                    "submission_id", StatusCode.CLIENT_ERROR
                )
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        user_ids = request_dict['users']
        submission_id = request_dict['submission_id']
        # Check if submission id is valid
        _, agency_name = sess.query(Submission.submission_id, CGAC.agency_name)\
            .join(CGAC, Submission.cgac_code == CGAC.cgac_code)\
            .filter(Submission.submission_id == submission_id).one()
        if not agency_name:
            _, agency_name = sess.query(Submission.submission_id, FREC.agency_name) \
                .join(FREC, Submission.frec_code == FREC.frec_code) \
                .filter(Submission.submission_id == submission_id).one()

        template_type = request_dict['email_template']
        # Check if email template type is valid
        get_email_template(template_type)

        users = []

        link = "".join([AccountHandler.FRONT_END, '#/reviewData/', str(submission_id)])
        email_template = {'[REV_USER_NAME]': g.user.name, '[REV_AGENCY]': agency_name, '[REV_URL]': link}

        for user_id in user_ids:
            # Check if user id is valid, if so add User object to array
            users.append(sess.query(User).filter(User.user_id == user_id).one())

        for user in users:
            new_email = SesEmail(user.email, system_email, template_type=template_type, parameters=email_template)
            new_email.send()

        return JsonResponse.create(StatusCode.OK, {"message": "Emails successfully sent"})
 def set_skip_guide(self):
     """ Set current user's skip guide parameter """
     sess = GlobalDB.db().session
     request_dict = RequestDictionary.derive(self.request)
     try:
         if 'skip_guide' not in request_dict:
             raise ResponseException("Must include skip_guide parameter",
                                     StatusCode.CLIENT_ERROR)
         skip_guide = str(request_dict['skip_guide']).lower()
         if skip_guide not in ("true", "false"):
             raise ResponseException("skip_guide must be true or false",
                                     StatusCode.CLIENT_ERROR)
         g.user.skip_guide = skip_guide == "true"
     except ResponseException as exc:
         return JsonResponse.error(exc, exc.status)
     sess.commit()
     return JsonResponse.create(StatusCode.OK, {
         "message": "skip_guide set successfully",
         "skip_guide": skip_guide
     })
 def set_skip_guide(self):
     """ Set current user's skip guide parameter """
     sess = GlobalDB.db().session
     request_dict = RequestDictionary.derive(self.request)
     try:
         if 'skip_guide' not in request_dict:
             raise ResponseException(
                 "Must include skip_guide parameter",
                 StatusCode.CLIENT_ERROR
             )
         skip_guide = str(request_dict['skip_guide']).lower()
         if skip_guide not in ("true", "false"):
             raise ResponseException(
                 "skip_guide must be true or false",
                 StatusCode.CLIENT_ERROR
             )
         g.user.skip_guide = skip_guide == "true"
     except ResponseException as exc:
         return JsonResponse.error(exc, exc.status)
     sess.commit()
     return JsonResponse.create(StatusCode.OK, {"message": "skip_guide set successfully", "skip_guide": skip_guide})
    def email_users(self, system_email, session):
        """ Send email notification to list of users """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)
        required = ('users', 'submission_id', 'email_template')
        try:
            if any(field not in request_dict for field in required):
                raise ResponseException(
                    "Email users route requires users, email_template, and "
                    "submission_id", StatusCode.CLIENT_ERROR
                )
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        current_user = sess.query(User).filter(User.user_id == session["name"]).one()

        user_ids = request_dict['users']
        submission_id = request_dict['submission_id']
        # Check if submission id is valid
        sess.query(Submission).filter_by(submission_id=submission_id).one()

        template_type = request_dict['email_template']
        # Check if email template type is valid
        get_email_template(template_type)

        users = []

        link = "".join([AccountHandler.FRONT_END, '#/reviewData/', str(submission_id)])
        email_template = {'[REV_USER_NAME]': current_user.name, '[REV_URL]': link}

        for user_id in user_ids:
            # Check if user id is valid, if so add User object to array
            users.append(sess.query(User).filter(User.user_id == user_id).one())

        for user in users:
            new_email = sesEmail(user.email, system_email, templateType=template_type, parameters=email_template)
            new_email.send()

        return JsonResponse.create(StatusCode.OK, {"message": "Emails successfully sent"})
 def set_skip_guide(self, session):
     """ Set current user's skip guide parameter """
     sess = GlobalDB.db().session
     user = sess.query(User).filter(User.user_id == session["name"]).one()
     request_dict = RequestDictionary.derive(self.request)
     try:
         if 'skip_guide' not in request_dict:
             raise ResponseException(
                 "Must include skip_guide parameter",
                 StatusCode.CLIENT_ERROR
             )
         skip_guide = request_dict['skip_guide']
         if isinstance(skip_guide, bool):    # e.g. from JSON
             user.skip_guide = skip_guide
         elif isinstance(skip_guide, str):
             # param is a string, allow "true" or "false"
             if skip_guide.lower() == "true":
                 user.skip_guide = True
             elif skip_guide.lower() == "false":
                 user.skip_guide = False
             else:
                 raise ResponseException(
                     "skip_guide must be true or false",
                     StatusCode.CLIENT_ERROR
                 )
         else:
             raise ResponseException(
                 "skip_guide must be a boolean", StatusCode.CLIENT_ERROR)
     except ResponseException as exc:
         return JsonResponse.error(exc, exc.status)
     sess.commit()
     return JsonResponse.create(
         StatusCode.OK,
         {"message": "skip_guide set successfully",
          "skip_guide":skip_guide}
     )
    def update_user(self, system_email):
        """
        Update editable fields for specified user. Editable fields for a user:
        * is_active
        * user_status_id

        Args:
            system_email: address the email is sent from

        Request body should contain the following keys:
            * uid (integer)
            * status (string)
            * is_active (boolean)

        Returns: JSON response object with either an exception or success message

        """
        sess = GlobalDB.db().session
        request_dict = RequestDictionary.derive(self.request)

        try:
            editable_fields = ('status', 'permissions', 'is_active')
            has_editable = any(key in request_dict for key in editable_fields)
            if 'uid' not in request_dict or not has_editable:
                # missing required fields, return 400
                raise ResponseException(
                    "Request body must include uid and at least one of the "
                    "following: status, permissions, is_active",
                    StatusCode.CLIENT_ERROR
                )
            # Find user that matches specified uid
            user = sess.query(User).filter_by(
                user_id=int(request_dict['uid'])).one_or_none()
            if user is None:
                raise ResponseException(
                    "No users with that uid", StatusCode.CLIENT_ERROR)
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        if 'status' in request_dict:
            #check if the user is waiting
            if user.user_status_id == USER_STATUS_DICT["awaiting_approval"]:
                if request_dict['status'] == 'approved':
                    # Grant agency_user permission to newly approved users
                    user.permission_type_id = PERMISSION_TYPE_DICT['reader']
                    sess.merge(user)
                    sess.commit()

                    link = AccountHandler.FRONT_END
                    email_template = {'[URL]':link,'[EMAIL]':system_email}
                    new_email = sesEmail(user.email, system_email,templateType="account_approved",parameters=email_template)
                    new_email.send()
                elif request_dict['status'] == 'denied':
                    email_template = {}
                    new_email = sesEmail(user.email, system_email,templateType="account_rejected",parameters=email_template)
                    new_email.send()
            # Change user's status
            try:
                user.user_status_id = USER_STATUS_DICT[request_dict['status']]
            except ValueError as e:
                # In this case having a bad status name is a client error
                raise ResponseException(str(e), StatusCode.CLIENT_ERROR, ValueError)
            sess.commit()

        # Activate/deactivate user
        if 'is_active' in request_dict:
            is_active = bool(request_dict['is_active'])
            user.is_active = is_active
            sess.commit()

        return JsonResponse.create(StatusCode.OK, {"message": "User successfully updated"})
    def register(self,system_email,session):
        """

        Save user's information into user database.  Associated request body should have keys 'email', 'name', 'cgac_code', 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 (username="", title="", cgac_code="", user_email="" , link="") :
            """
            This inner function sends emails in a new thread as there could be lots of admins

            username -- (string) the name of the  user
            title  --   (string) the title of the  user
            cgac_code -- (string) the agency of the  user
            user_email -- (string) the email of the user
            link  -- (string) the broker email link
            """
            agency_name = sess.query(CGAC.agency_name).\
                filter(CGAC.cgac_code == cgac_code).\
                one_or_none()
            agency_name = "Unknown" if agency_name is None else agency_name
            for user in sess.query(User).filter_by(permission_type_id=PERMISSION_TYPE_DICT['website_admin']):
                email_template = {'[REG_NAME]': username, '[REG_TITLE]':title, '[REG_AGENCY_NAME]':agency_name,
                                 '[REG_CGAC_CODE]': cgac_code,'[REG_EMAIL]' : user_email,'[URL]':link}
                new_email = sesEmail(user.email, system_email,templateType="account_creation",parameters=email_template)
                new_email.send()

        sess = GlobalDB.db().session
        request_fields = RequestDictionary.derive(self.request)
        try:
            required = ('email', 'name', 'cgac_code', 'title', 'password')
            if any(field not in request_fields for field in required):
                # Missing a required field, return 400
                raise ResponseException(
                    "Request body must include email, name, cgac_code, "
                    "title, and password", StatusCode.CLIENT_ERROR
                )
            if not self.checkPassword(request_fields["password"]):
                raise ResponseException(
                    "Invalid Password", StatusCode.CLIENT_ERROR)
            # Find user that matches specified email
            user = sess.query(User).filter(
                func.lower(User.email) == func.lower(request_fields['email'])
            ).one_or_none()
            if user is None:
                raise ResponseException(
                    "No users with that email", StatusCode.CLIENT_ERROR)
            # Check that user's status is before submission of registration
            bad_statuses = (USER_STATUS_DICT["awaiting_confirmation"], USER_STATUS_DICT["email_confirmed"])
            if user.user_status_id not in bad_statuses:
                # Do not allow duplicate registrations
                raise ResponseException(
                    "User already registered", StatusCode.CLIENT_ERROR)
            # Add user info to database
            user.name = request_fields['name']
            user.cgac_code = request_fields['cgac_code']
            user.title = request_fields['title']
            sess.commit()
            set_user_password(user, request_fields['password'], self.bcrypt)
        except ResponseException as exc:
            return JsonResponse.error(exc, exc.status)

        user_link= "".join([AccountHandler.FRONT_END, '#/login?redirect=/admin'])
        # Send email to approver list
        email_thread = Thread(target=ThreadedFunction, kwargs=dict(username=user.name,title=user.title,cgac_code=user.cgac_code,user_email=user.email,link=user_link))
        email_thread.start()

        #email user
        email_template = {'[EMAIL]' : system_email}
        new_email = sesEmail(user.email, system_email,templateType="account_creation_user",parameters=email_template)
        new_email.send()

        # Logout and delete token
        LoginSession.logout(session)
        oldToken = sess.query(EmailToken).filter(EmailToken.token == session["token"]).one()
        sess.delete(oldToken)
        # Mark user as awaiting approval
        user.user_status_id = USER_STATUS_DICT["awaiting_approval"]
        sess.commit()
        return JsonResponse.create(StatusCode.OK,{"message":"Registration successful"})