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)
        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 ThreadedFunction (from_email="",username="",title="",cgac_code="",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:
                agency_name = self.interfaces.validationDb.getAgencyName(cgac_code)
                agency_name = "Unknown" if agency_name is None else agency_name
                for user in threadedDatabase.getUsersByType("website_admin"):
                    emailTemplate = {'[REG_NAME]': username, '[REG_TITLE]':title, '[REG_AGENCY_NAME]':agency_name,
                                     '[REG_CGAC_CODE]': cgac_code,'[REG_EMAIL]' : userEmail,'[URL]':link}
                    newEmail = sesEmail(user.email, system_email,templateType="account_creation",parameters=emailTemplate,database=threadedDatabase)
                    newEmail.send()
                for user in threadedDatabase.getUsersByType("agency_admin"):
                    if user.cgac_code == cgac_code:
                        emailTemplate = {'[REG_NAME]': username, '[REG_TITLE]': title, '[REG_AGENCY_NAME]': agency_name,
                             '[REG_CGAC_CODE]': cgac_code,'[REG_EMAIL]': userEmail, '[URL]': link}
                        newEmail = sesEmail(user.email, system_email, templateType="account_creation", parameters=emailTemplate,
                                database=threadedDatabase)
                        newEmail.send()

            finally:
                InterfaceHolder.closeOne(threadedDatabase)
Example #4
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 ThreadedFunction(from_email="",
                             username="",
                             title="",
                             cgac_code="",
                             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:
                agency_name = self.interfaces.validationDb.getAgencyName(
                    cgac_code)
                agency_name = "Unknown" if agency_name is None else agency_name
                for user in threadedDatabase.getUsersByType("website_admin"):
                    emailTemplate = {
                        '[REG_NAME]': username,
                        '[REG_TITLE]': title,
                        '[REG_AGENCY_NAME]': agency_name,
                        '[REG_CGAC_CODE]': cgac_code,
                        '[REG_EMAIL]': userEmail,
                        '[URL]': link
                    }
                    newEmail = sesEmail(user.email,
                                        system_email,
                                        templateType="account_creation",
                                        parameters=emailTemplate,
                                        database=threadedDatabase)
                    newEmail.send()
                for user in threadedDatabase.getUsersByType("agency_admin"):
                    if user.cgac_code == cgac_code:
                        emailTemplate = {
                            '[REG_NAME]': username,
                            '[REG_TITLE]': title,
                            '[REG_AGENCY_NAME]': agency_name,
                            '[REG_CGAC_CODE]': cgac_code,
                            '[REG_EMAIL]': userEmail,
                            '[URL]': link
                        }
                        newEmail = sesEmail(user.email,
                                            system_email,
                                            templateType="account_creation",
                                            parameters=emailTemplate,
                                            database=threadedDatabase)
                        newEmail.send()

            finally:
                InterfaceHolder.closeOne(threadedDatabase)
Example #6
0
    def sendResetPasswordEmail(self,
                               user,
                               system_email,
                               email=None,
                               unlock_user=False):
        if email is None:
            email = user.email

        # User must be approved and active to reset password
        if user.user_status_id != self.interfaces.userDb.getUserStatusId(
                "approved"):
            raise ResponseException(
                "User must be approved before resetting password",
                StatusCode.CLIENT_ERROR)
        elif not unlock_user and not user.is_active:
            raise ResponseException("User is locked, cannot reset password",
                                    StatusCode.CLIENT_ERROR)

        # If unlocking a user, wipe out current password
        if unlock_user:
            UserHandler().clearPassword(user)

        self.interfaces.userDb.session.commit()
        # Send email with token
        emailToken = sesEmail.createToken(email, "password_reset")
        link = "".join(
            [AccountHandler.FRONT_END, '#/forgotpassword/', emailToken])
        emailTemplate = {'[URL]': link}
        templateType = "unlock_account" if unlock_user else "reset_password"
        newEmail = sesEmail(user.email,
                            system_email,
                            templateType=templateType,
                            parameters=emailTemplate,
                            database=self.interfaces.userDb)
        newEmail.send()
        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)
Example #8
0
def test_delete_user(database):
    user_handler = UserHandler()
    # Create user with email
    user_to_be_deleted = UserFactory()
    email = user_to_be_deleted.email
    other_user = UserFactory()
    database.session.add_all([user_to_be_deleted, other_user])
    database.session.commit()
    # Create two submissions for this user and one for a different user
    sub_one = SubmissionFactory(user_id=user_to_be_deleted.user_id)
    sub_two = SubmissionFactory(user_id=user_to_be_deleted.user_id)
    other_sub = SubmissionFactory(user_id=other_user.user_id)
    database.session.add_all([sub_one, sub_two, other_sub])
    database.session.commit()
    # Delete a user
    user_handler.deleteUser(email)
    # Confirm user has been deleted and that user's submissions have no user_id
    assert database.session.query(User).filter_by(email=email).count() == 0
    assert sub_one.user_id is None
    assert sub_two.user_id is None
    # Confirm that other submission was not affected
    assert other_sub.user_id == other_user.user_id
 def __init__(self):
     """ Create the interfaces """
     if BaseInterface.interfaces is None:
         self.jobDb = JobHandler()
         self.errorDb = ErrorHandler()
         self.userDb = UserHandler()
         self.validationDb = ValidationInterface()
         self.stagingDb = self.validationDb
         BaseInterface.interfaces = self
     else:
         self.jobDb = BaseInterface.interfaces.jobDb
         self.errorDb = BaseInterface.interfaces.errorDb
         self.userDb = BaseInterface.interfaces.userDb
         self.validationDb = BaseInterface.interfaces.validationDb
         self.stagingDb = self.validationDb
Example #10
0
def createAdmin():
    """Create initial admin user."""
    adminEmail = CONFIG_BROKER['admin_email']
    adminPass = CONFIG_BROKER['admin_password']
    userDb = UserHandler()
    try:
        user = userDb.getUserByEmail(adminEmail)
    except ResponseException as e:

        if type(e.wrappedException) is NoResultFound:
            userDb.createUserWithPassword(adminEmail,
                                          adminPass,
                                          Bcrypt(),
                                          admin=True)
            user = userDb.getUserByEmail(adminEmail)
            userDb.addUserInfo(user, "Admin", "System", "System Admin")
    userDb.session.close()
Example #11
0
    def emailUsers(self, system_email, session):
        """ Send email notification to list of users """
        requestDict = RequestDictionary(self.request)
        if not (requestDict.exists("users")
                and requestDict.exists("submission_id")
                and requestDict.exists("email_template")):
            exc = ResponseException(
                "Email users route requires users, email_template, and submission_id",
                StatusCode.CLIENT_ERROR)
            return JsonResponse.error(exc, exc.status)

        uid = session["name"]
        current_user = self.interfaces.userDb.getUserByUID(uid)

        user_ids = requestDict.getValue("users")
        submission_id = requestDict.getValue("submission_id")
        # Check if submission id is valid
        self.jobManager.getSubmissionById(submission_id)

        template_type = requestDict.getValue("email_template")
        # Check if email template type is valid
        self.userManager.getEmailTemplate(template_type)

        users = []

        link = "".join(
            [AccountHandler.FRONT_END, '#/reviewData/',
             str(submission_id)])
        emailTemplate = {
            '[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(self.userManager.getUserByUID(user_id))

        for user in users:
            newEmail = sesEmail(user.email,
                                system_email,
                                templateType=template_type,
                                parameters=emailTemplate,
                                database=UserHandler())
            newEmail.send()

        return JsonResponse.create(StatusCode.OK,
                                   {"message": "Emails successfully sent"})
def createAdmin():
    """Create initial admin user."""
    adminEmail = CONFIG_BROKER['admin_email']
    adminPass = CONFIG_BROKER['admin_password']
    userDb = UserHandler()
    try:
        user = userDb.getUserByEmail(adminEmail)
    except ResponseException as e:

        if type(e.wrappedException) is NoResultFound:
            userDb.createUserWithPassword(
                adminEmail, adminPass, Bcrypt(), permission=2)
            user = userDb.getUserByEmail(adminEmail)
            userDb.addUserInfo(user, "Admin", "SYS", "System Admin")
    userDb.session.close()
Example #13
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)
def setupEmails():
    """Create email templates from model metadata."""
    userDb = UserHandler()

    # insert email template types
    typeList = [
        ('validate_email', ''),
        ('account_approved', ''),
        ('account_rejected', ''),
        ('reset_password', ''),
        ('account_creation', ''),
        ('account_creation_user', '')
    ]
    for t in typeList:
        emailId = userDb.session.query(
            EmailTemplateType.email_template_type_id).filter(
            EmailTemplateType.name == t[0]).one_or_none()
        if not emailId:
            type = EmailTemplateType(name=t[0], description=t[1])
            userDb.session.add(type)

    # insert email templates

    #Confirm
    template = "This email address was just used to create a user account with the DATA Act Broker.  To continue the registration process, please click <a href='[URL]'>here</a>. The link will expire in 24 hours. <br />  <br />  If you did not initiate this process, you may disregard this email.<br /><br />The DATA Act Broker Helpdesk<br />[email protected] "
    userDb.loadEmailTemplate("DATA Act Broker - Registration", template, "validate_email")

    #Approve
    template = "Thank you for registering for a user account with the DATA Act Broker. Your request has been approved by the DATA Act Broker Help Desk. You may now log into the Data Broker portal, using the password you created at registration, by clicking <a href='[URL]'>here</a>.<br /><br /> If you have any questions, please contact the DATA Act Broker Help Desk at [EMAIL].<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Access Approved", template, "account_approved")

    #Reject
    template = "Thank you for requesting log-in credentials for the DATA Act Broker. Your attempt to register has been denied. If you believe this determination was made in error, please contact the DATA Act Broker Helpdesk at [email protected].<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Access Denied", template, "account_rejected")

    #Password Reset
    template = "You have requested your password to be reset for your account. Please click the following link <a href='[URL]'>here</a> to start the processs. The link will expire in 24 hours. <br/> <br/> If you did not request this password reset, please notify the DATA Act Broker Helpdesk ([email protected]) <br /><br />DATA Act Broker Helpdesk<br /><br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Password Reset", template, "reset_password")

    #Admin Email
    template = "This email is to notify you that the following person has requested an account for the DATA Act Broker:<br /><br />Name: [REG_NAME]<br /><br />Title:  [REG_TITLE]<br /><br />Agency:  [REG_AGENCY]<br /><br />Email: [REG_EMAIL]<br /><br /><br /><br />To approve or deny this user for access to the Data Broker, please click <a href='[URL]'>here</a>.<br /><br />This action must be taken within 24 hours. <br /><br />Thank you for your prompt attention.<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("New Data Broker registration - Action Required", template, "account_creation")

    #User Email When finished submitting
    template = ("Thank you for registering a DATA Act Broker user account. "
        "The final registration step is for the Help Desk to review your "
        "request. You should receive an e-mail update from them within one "
        "business day, saying whether they've approved or denied your access."
        "<br /><br />"
        "Until the Help Desk approves your request, you won't be able to log "
        "into the Broker. Thanks for being patient with the security process--"
        "we appreciate your interest and look forward to working with you."
        "<br /><br/>"
        "If you have any questions or haven't received a follow-up e-mail "
        "within one business day, please get in touch with the Help Desk at "
        "[EMAIL]."
        "<br /><br />"
        "The DATA Act Implementation Team <br />"
        "[EMAIL]")
    userDb.loadEmailTemplate("DATA Act Broker - Registration", template, "account_creation_user")

    InterfaceHolder.closeOne(userDb)
    def setUpClass(cls):
        """Set up resources to be shared within a test class"""
        # TODO: refactor into a pytest class fixtures and inject as necessary

        # update application's db config options so unittests
        # run against test databases
        suite = cls.__name__.lower()
        config = dataactcore.config.CONFIG_DB
        cls.num = randint(1, 9999)
        config["error_db_name"] = "unittest{}_{}_error_data".format(cls.num, suite)
        config["job_db_name"] = "unittest{}_{}_job_tracker".format(cls.num, suite)
        config["user_db_name"] = "unittest{}_{}_user_manager".format(cls.num, suite)
        config["validator_db_name"] = "unittest{}_{}_validator".format(cls.num, suite)
        config["staging_db_name"] = "unittest{}_{}_staging".format(cls.num, suite)
        dataactcore.config.CONFIG_DB = config

        # suppress INFO-level logging from Alembic migrations
        logging.disable(logging.WARN)
        # create test user db
        setupUserDB()
        # create test job db
        setupJobTrackerDB()
        # create test error db
        setupErrorDB()
        # load e-mail templates
        setupEmails()
        # reset logging defaults
        logging.disable(logging.NOTSET)

        # get test users
        try:
            with open("test.json") as test_users_file:
                test_users = json.load(test_users_file)
            test_users = test_users
        except:
            # if no test.json, provide some default e-mail accounts for tests
            test_users = {}
            test_users["admin_email"] = "*****@*****.**"
            test_users["change_user_email"] = "*****@*****.**"
            test_users["password_reset_email"] = "*****@*****.**"
            test_users["inactive_email"] = "*****@*****.**"
        if "approved_email" not in test_users:
            test_users["approved_email"] = "*****@*****.**"
        if "submission_email" not in test_users:
            test_users["submission_email"] = "*****@*****.**"
        user_password = "******"
        admin_password = "******"

        # setup test users
        userEmails = [
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
            "*****@*****.**",
            test_users["admin_email"],
            test_users["approved_email"],
            "*****@*****.**",
        ]
        userStatus = [
            "awaiting_confirmation",
            "email_confirmed",
            "awaiting_approval",
            "awaiting_approval",
            "awaiting_approval",
            "approved",
            "approved",
            "denied",
        ]
        userPermissions = [
            0,
            AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
            AccountType.WEBSITE_ADMIN + AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
        ]

        # Add new users
        userDb = UserHandler()
        userDb.createUserWithPassword(test_users["submission_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["change_user_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["password_reset_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["inactive_email"], user_password, Bcrypt())

        # Create users for status testing
        for index in range(len(userEmails)):
            email = userEmails[index]
            userDb.addUnconfirmedEmail(email)
            user = userDb.getUserByEmail(email)
            userDb.changeStatus(user, userStatus[index])
            userDb.setPermission(user, userPermissions[index])

        # set up approved user
        user = userDb.getUserByEmail(test_users["approved_email"])
        user.username = "******"
        userDb.setPassword(user, user_password, Bcrypt())
        cls.approved_user_id = user.user_id

        # set up admin user
        admin = userDb.getUserByEmail(test_users["admin_email"])
        userDb.setPassword(admin, admin_password, Bcrypt())
        admin.name = "Mr. Manager"
        admin.agency = "Unknown"
        userDb.session.commit()

        # set up status changed user
        statusChangedUser = userDb.getUserByEmail(test_users["change_user_email"])
        cls.status_change_user_id = statusChangedUser.user_id
        statusChangedUser.name = "Test User"
        statusChangedUser.user_status_id = userDb.getUserStatusId("email_confirmed")
        userDb.session.commit()

        # set up deactivated user
        user = userDb.getUserByEmail(test_users["inactive_email"])
        user.last_login_date = time.strftime("%c")
        user.is_active = False
        userDb.session.commit()

        # set up info needed by the individual test classes
        cls.test_users = test_users
        cls.user_password = user_password
        cls.admin_password = admin_password
        cls.interfaces = InterfaceHolder()
        cls.jobTracker = cls.interfaces.jobDb
        cls.errorDatabase = cls.interfaces.errorDb
        cls.userDb = cls.interfaces.userDb
        cls.local = CONFIG_BROKER["local"]
Example #16
0
    def setUpClass(cls):
        """Set up resources to be shared within a test class"""
        #TODO: refactor into a pytest class fixtures and inject as necessary

        # update application's db config options so unittests
        # run against test databases
        suite = cls.__name__.lower()
        config = dataactcore.config.CONFIG_DB
        cls.num = randint(1, 9999)
        config['error_db_name'] = 'unittest{}_{}_error_data'.format(
            cls.num, suite)
        config['job_db_name'] = 'unittest{}_{}_job_tracker'.format(
            cls.num, suite)
        config['user_db_name'] = 'unittest{}_{}_user_manager'.format(
            cls.num, suite)
        config['validator_db_name'] = 'unittest{}_{}_validator'.format(
            cls.num, suite)
        config['staging_db_name'] = 'unittest{}_{}_staging'.format(
            cls.num, suite)
        dataactcore.config.CONFIG_DB = config

        # suppress INFO-level logging from Alembic migrations
        logging.disable(logging.WARN)
        # create test user db
        setupUserDB()
        # create test job db
        setupJobTrackerDB()
        # create test error db
        setupErrorDB()
        # load e-mail templates
        setupEmails()
        # reset logging defaults
        logging.disable(logging.NOTSET)

        #get test users
        try:
            with open('test.json') as test_users_file:
                test_users = json.load(test_users_file)
            test_users = test_users
        except:
            #if no test.json, provide some default e-mail accounts for tests
            test_users = {}
            test_users['admin_email'] = '*****@*****.**'
            test_users['change_user_email'] = '*****@*****.**'
            test_users['password_reset_email'] = '*****@*****.**'
            test_users['inactive_email'] = '*****@*****.**'
        if 'approved_email' not in test_users:
            test_users['approved_email'] = '*****@*****.**'
        if 'submission_email' not in test_users:
            test_users['submission_email'] = '*****@*****.**'
        user_password = '******'
        admin_password = '******'

        #setup test users
        userEmails = [
            "*****@*****.**", "*****@*****.**", "*****@*****.**",
            "*****@*****.**", "*****@*****.**",
            test_users["admin_email"], test_users["approved_email"],
            "*****@*****.**"
        ]
        userStatus = [
            "awaiting_confirmation", "email_confirmed", "awaiting_approval",
            "awaiting_approval", "awaiting_approval", "approved", "approved",
            "denied"
        ]
        userPermissions = [
            0, AccountType.AGENCY_USER, AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER,
            AccountType.WEBSITE_ADMIN + AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER
        ]

        # Add new users
        userDb = UserHandler()
        userDb.createUserWithPassword(test_users["submission_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["change_user_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["password_reset_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["inactive_email"],
                                      user_password, Bcrypt())

        # Create users for status testing
        for index in range(len(userEmails)):
            email = userEmails[index]
            userDb.addUnconfirmedEmail(email)
            user = userDb.getUserByEmail(email)
            userDb.changeStatus(user, userStatus[index])
            userDb.setPermission(user, userPermissions[index])

        #set up approved user
        user = userDb.getUserByEmail(test_users['approved_email'])
        user.username = "******"
        userDb.setPassword(user, user_password, Bcrypt())
        cls.approved_user_id = user.user_id

        #set up admin user
        admin = userDb.getUserByEmail(test_users['admin_email'])
        userDb.setPassword(admin, admin_password, Bcrypt())
        admin.name = "Mr. Manager"
        admin.agency = "Unknown"
        userDb.session.commit()

        #set up status changed user
        statusChangedUser = userDb.getUserByEmail(
            test_users["change_user_email"])
        cls.status_change_user_id = statusChangedUser.user_id
        statusChangedUser.name = "Test User"
        statusChangedUser.user_status_id = userDb.getUserStatusId(
            "email_confirmed")
        userDb.session.commit()

        #set up deactivated user
        user = userDb.getUserByEmail(test_users["inactive_email"])
        user.last_login_date = time.strftime("%c")
        user.is_active = False
        userDb.session.commit()

        #set up info needed by the individual test classes
        cls.test_users = test_users
        cls.user_password = user_password
        cls.admin_password = admin_password
        cls.interfaces = InterfaceHolder()
        cls.jobTracker = cls.interfaces.jobDb
        cls.errorDatabase = cls.interfaces.errorDb
        cls.userDb = cls.interfaces.userDb
        cls.local = CONFIG_BROKER['local']
    def setUpClass(cls):
        """Set up resources to be shared within a test class"""
        #TODO: refactor into a pytest class fixtures and inject as necessary

        # Create an empty session ID
        cls.session_id = ""

        # update application's db config options so unittests
        # run against test databases
        suite = cls.__name__.lower()
        config = dataactcore.config.CONFIG_DB
        cls.num = randint(1, 9999)
        config['error_db_name'] = 'unittest{}_{}_error_data'.format(
            cls.num, suite)
        config['job_db_name'] = 'unittest{}_{}_job_tracker'.format(
            cls.num, suite)
        config['user_db_name'] = 'unittest{}_{}_user_manager'.format(
            cls.num, suite)
        config['validator_db_name'] = 'unittest{}_{}_validator'.format(
            cls.num, suite)
        config['staging_db_name'] = 'unittest{}_{}_staging'.format(
            cls.num, suite)
        dataactcore.config.CONFIG_DB = config

        # drop and re-create test user db/tables
        setupUserDB()
        # drop and re-create test job db/tables
        setupJobTrackerDB()
        # drop and re-create test error db/tables
        setupErrorDB()
        # drop and re-create test validation db/tables
        setupValidationDB()
        # load e-mail templates
        setupEmails()

        #get test users
        try:
            with open('test.json') as test_users_file:
                test_users = json.load(test_users_file)
            test_users = test_users
        except:
            #if no test.json, provide some default e-mail accounts for tests
            test_users = {}
            test_users['admin_email'] = '*****@*****.**'
            test_users['change_user_email'] = '*****@*****.**'
            test_users['password_reset_email'] = '*****@*****.**'
            test_users['inactive_email'] = '*****@*****.**'
            test_users['password_lock_email'] = '*****@*****.**'
            test_users['expired_lock_email'] = '*****@*****.**'
            test_users['agency_admin_email'] = '*****@*****.**'

            # This email is for a regular agency_user email that is to be used for testing functionality
            # expected by a normal, base user
            test_users['agency_user'] = '******'
        if 'approved_email' not in test_users:
            test_users['approved_email'] = '*****@*****.**'
        if 'submission_email' not in test_users:
            test_users['submission_email'] = '*****@*****.**'
        user_password = '******'
        admin_password = '******'

        #setup test users
        userEmails = ["*****@*****.**", "*****@*****.**",
            "*****@*****.**", "*****@*****.**",
            "*****@*****.**", test_users["admin_email"],
            test_users["approved_email"], "*****@*****.**"]
        userStatus = ["awaiting_confirmation",
            "email_confirmed", "awaiting_approval",
            "awaiting_approval", "awaiting_approval",
            "approved", "approved", "denied"]
        userPermissions = [0, AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER,
            AccountType.AGENCY_USER,
            AccountType.WEBSITE_ADMIN+AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER]

        # Add new users
        userDb = UserHandler()
        userDb.createUserWithPassword(
            test_users["submission_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users["change_user_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users["password_reset_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users["inactive_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users["password_lock_email"], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users['expired_lock_email'], user_password, Bcrypt())
        userDb.createUserWithPassword(
            test_users['agency_admin_email'], admin_password, Bcrypt(), permission=4)
        userDb.createUserWithPassword(
            test_users['agency_user'], user_password, Bcrypt())

        # Set the Agency for the agency user
        agencyUser = userDb.getUserByEmail(test_users['agency_user'])
        userDb.session.commit()
        cls.agency_user_id = agencyUser.user_id

        # Set the specified account to be expired
        expiredUser = userDb.getUserByEmail(test_users['expired_lock_email'])
        today = parse(time.strftime("%c"))
        expiredUser.last_login_date = (today-timedelta(days=120)).strftime("%c")
        userDb.session.commit()

        # Create users for status testing
        for index in range(len(userEmails)):
            email = userEmails[index]
            userDb.addUnconfirmedEmail(email)
            user = userDb.getUserByEmail(email)
            userDb.changeStatus(user, userStatus[index])
            userDb.setPermission(user, userPermissions[index])

        #set up approved user
        user = userDb.getUserByEmail(test_users['approved_email'])
        user.username = "******"
        userDb.setPassword(user, user_password, Bcrypt())
        cls.approved_user_id = user.user_id

        #set up admin user
        admin = userDb.getUserByEmail(test_users['admin_email'])
        userDb.setPassword(admin, admin_password, Bcrypt())
        admin.name = "Mr. Manager"
        admin.cgac_code = "SYS"
        userDb.session.commit()

        #set up status changed user
        statusChangedUser = userDb.getUserByEmail(
            test_users["change_user_email"])
        cls.status_change_user_id = statusChangedUser.user_id
        statusChangedUser.name = "Test User"
        statusChangedUser.user_status_id = userDb.getUserStatusId(
            "email_confirmed")
        userDb.session.commit()

        #set up deactivated user
        user = userDb.getUserByEmail(test_users["inactive_email"])
        user.last_login_date = time.strftime("%c")
        user.is_active = False
        userDb.session.commit()

        #set up info needed by the individual test classes
        cls.test_users = test_users
        cls.user_password = user_password
        cls.admin_password = admin_password
        cls.interfaces = InterfaceHolder()
        cls.jobTracker = cls.interfaces.jobDb
        cls.errorDatabase = cls.interfaces.errorDb
        cls.userDb = cls.interfaces.userDb
        cls.local = CONFIG_BROKER['local']
 def __init__(self):
     """ Create the interfaces """
     self.jobDb = JobHandler()
     self.errorDb = ErrorHandler()
     self.userDb = UserHandler()
Example #19
0
    def max_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)

            # Obtain POST content
            ticket = safeDictionary.getValue("ticket")
            service = safeDictionary.getValue('service')
            parent_group = CONFIG_BROKER['parent_group']

            # Call MAX's serviceValidate endpoint and retrieve the response
            max_dict = self.get_max_dict(ticket, service)

            if not 'cas:authenticationSuccess' in max_dict[
                    'cas:serviceResponse']:
                raise ValueError(
                    "You have failed to login successfully with MAX")

            # Grab the email and list of groups from MAX's response
            email = max_dict['cas:serviceResponse'][
                'cas:authenticationSuccess']['cas:attributes'][
                    'maxAttribute:Email-Address']
            group_list_all = max_dict['cas:serviceResponse'][
                'cas:authenticationSuccess']['cas:attributes'][
                    'maxAttribute:GroupList'].split(',')
            group_list = [
                g for g in group_list_all if g.startswith(parent_group)
            ]

            # Deny access if not in the parent group aka they're not allowed to access the website all together
            if not parent_group in group_list:
                raise ValueError(
                    "You have logged in with MAX but do not have permission to access the broker. Please "
                    "contact [email protected] to obtain access.")

            cgac_group = [
                g for g in group_list
                if len(g) == len(parent_group + "-CGAC_") + 3
            ]

            # Deny access if they are not aligned with an agency
            if not cgac_group:
                raise ValueError(
                    "You have logged in with MAX but do not have permission to access the broker. Please "
                    "contact [email protected] to obtain access.")

            try:
                sess = GlobalDB.db().session
                user = sess.query(User).filter(
                    func.lower(User.email) == func.lower(email)).one_or_none()

                # If the user does not exist, create them since they are allowed to access the site because they got
                # past the above group membership checks
                if user is None:
                    user = User()

                    first_name = max_dict["cas:serviceResponse"][
                        'cas:authenticationSuccess']['cas:attributes'][
                            'maxAttribute:First-Name']
                    middle_name = max_dict["cas:serviceResponse"][
                        'cas:authenticationSuccess']['cas:attributes'][
                            'maxAttribute:Middle-Name']
                    last_name = max_dict["cas:serviceResponse"][
                        'cas:authenticationSuccess']['cas:attributes'][
                            'maxAttribute:Last-Name']

                    user.email = email

                    # Check for None first so the condition can short-circuit without
                    # having to worry about calling strip() on a None object
                    if middle_name is None or middle_name.strip() == '':
                        user.name = first_name + " " + last_name
                    else:
                        user.name = first_name + " " + middle_name[
                            0] + ". " + last_name
                    user.user_status_id = user.user_status_id = USER_STATUS_DICT[
                        'approved']

                    # If part of the SYS agency, use that as the cgac otherwise use the first agency provided
                    if [g for g in cgac_group if g.endswith("SYS")]:
                        user.cgac_code = "SYS"
                        # website admin permissions
                        UserHandler().grantPermission(user, 'website_admin')
                    else:
                        user.cgac_code = cgac_group[0][-3:]
                        # regular user permissions
                        UserHandler().grantPermission(user, 'agency_user')

                    sess.add(user)
                    sess.commit()

            except MultipleResultsFound:
                raise ValueError("An error occurred during login.")

            return self.create_session_and_response(session, user)

        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
Example #20
0
def setupEmails():
    """Create email templates from model metadata."""
    userDb = UserHandler()

    # insert email template types
    typeList = [('validate_email', ''), ('account_approved', ''),
                ('account_rejected', ''), ('reset_password', ''),
                ('account_creation', ''), ('account_creation_user', ''),
                ('unlock_account', '')]
    for t in typeList:
        emailId = userDb.session.query(
            EmailTemplateType.email_template_type_id).filter(
                EmailTemplateType.name == t[0]).one_or_none()
        if not emailId:
            type = EmailTemplateType(name=t[0], description=t[1])
            userDb.session.add(type)

    # insert email templates

    #Confirm
    template = "This email address was just used to create a user account with the DATA Act Broker.  To continue the registration process, please click <a href='[URL]'>here</a>. The link will expire in 24 hours. <br />  <br />  If you did not initiate this process, you may disregard this email.<br /><br />The DATA Act Broker Helpdesk<br />[email protected] "
    userDb.loadEmailTemplate("DATA Act Broker - Registration", template,
                             "validate_email")

    #Approve
    template = "Thank you for registering for a user account with the DATA Act Broker. Your request has been approved by the DATA Act Broker Help Desk. You may now log into the Data Broker portal, using the password you created at registration, by clicking <a href='[URL]'>here</a>.<br /><br /> If you have any questions, please contact the DATA Act Broker Help Desk at [EMAIL].<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Access Approved", template,
                             "account_approved")

    #Reject
    template = "Thank you for requesting log-in credentials for the DATA Act Broker. Your attempt to register has been denied. If you believe this determination was made in error, please contact the DATA Act Broker Helpdesk at [email protected].<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Access Denied", template,
                             "account_rejected")

    #Password Reset
    template = "You have requested your password to be reset for your account. Please click the following link <a href='[URL]'>here</a> to start the processs. The link will expire in 24 hours. <br/> <br/> If you did not request this password reset, please notify the DATA Act Broker Helpdesk ([email protected]) <br /><br />DATA Act Broker Helpdesk<br /><br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Password Reset", template,
                             "reset_password")

    #Admin Email
    template = "This email is to notify you that the following person has requested an account for the DATA Act Broker:<br /><br />Name: [REG_NAME]<br /><br />Title:  [REG_TITLE]<br /><br />Agency Name:  [REG_AGENCY_NAME]<br /><br />CGAC Code: [REG_CGAC_CODE]<br /><br />Email: [REG_EMAIL]<br /><br /><br /><br />To approve or deny this user for access to the Data Broker, please click <a href='[URL]'>here</a>.<br /><br />This action must be taken within 24 hours. <br /><br />Thank you for your prompt attention.<br /><br />DATA Act Broker Helpdesk<br />[email protected]"
    userDb.loadEmailTemplate("New Data Broker registration - Action Required",
                             template, "account_creation")

    #User Email When finished submitting
    template = (
        "Thank you for registering a DATA Act Broker user account. "
        "The final registration step is for the Help Desk to review your "
        "request. You should receive an e-mail update from them within one "
        "business day, saying whether they've approved or denied your access."
        "<br /><br />"
        "Until the Help Desk approves your request, you won't be able to log "
        "into the Broker. Thanks for being patient with the security process--"
        "we appreciate your interest and look forward to working with you."
        "<br /><br/>"
        "If you have any questions or haven't received a follow-up e-mail "
        "within one business day, please get in touch with the Help Desk at "
        "[EMAIL]."
        "<br /><br />"
        "The DATA Act Implementation Team <br />"
        "[EMAIL]")
    userDb.loadEmailTemplate("DATA Act Broker - Registration", template,
                             "account_creation_user")

    #Unlock account email
    template = "Your account has been unlocked and requires your password to be reset. Please click the following link <a href='[URL]'>here</a> to start the processs. The link will expire in 24 hours. <br/> <br/> If you did not request your account to be unlocked, please notify the DATA Act Broker Helpdesk ([email protected]) <br /><br />DATA Act Broker Helpdesk<br /><br />[email protected]"
    userDb.loadEmailTemplate("DATA Act Broker - Password Reset", template,
                             "unlock_account")

    InterfaceHolder.closeOne(userDb)
Example #21
0
    def setUpClass(cls):
        """Set up resources to be shared within a test class"""
        #TODO: refactor into a pytest class fixtures and inject as necessary

        # Create an empty session ID
        cls.session_id = ""

        # update application's db config options so unittests
        # run against test databases
        suite = cls.__name__.lower()
        config = dataactcore.config.CONFIG_DB
        cls.num = randint(1, 9999)
        config['error_db_name'] = 'unittest{}_{}_error_data'.format(
            cls.num, suite)
        config['job_db_name'] = 'unittest{}_{}_job_tracker'.format(
            cls.num, suite)
        config['user_db_name'] = 'unittest{}_{}_user_manager'.format(
            cls.num, suite)
        config['validator_db_name'] = 'unittest{}_{}_validator'.format(
            cls.num, suite)
        config['staging_db_name'] = 'unittest{}_{}_staging'.format(
            cls.num, suite)
        dataactcore.config.CONFIG_DB = config

        # drop and re-create test user db/tables
        setupUserDB()
        # drop and re-create test job db/tables
        setupJobTrackerDB()
        # drop and re-create test error db/tables
        setupErrorDB()
        # drop and re-create test validation db/tables
        setupValidationDB()
        # load e-mail templates
        setupEmails()

        #get test users
        try:
            with open('test.json') as test_users_file:
                test_users = json.load(test_users_file)
            test_users = test_users
        except:
            #if no test.json, provide some default e-mail accounts for tests
            test_users = {}
            test_users['admin_email'] = '*****@*****.**'
            test_users['change_user_email'] = '*****@*****.**'
            test_users['password_reset_email'] = '*****@*****.**'
            test_users['inactive_email'] = '*****@*****.**'
            test_users['password_lock_email'] = '*****@*****.**'
            test_users['expired_lock_email'] = '*****@*****.**'
            test_users['agency_admin_email'] = '*****@*****.**'

            # This email is for a regular agency_user email that is to be used for testing functionality
            # expected by a normal, base user
            test_users['agency_user'] = '******'
        if 'approved_email' not in test_users:
            test_users['approved_email'] = '*****@*****.**'
        if 'submission_email' not in test_users:
            test_users['submission_email'] = '*****@*****.**'
        user_password = '******'
        admin_password = '******'

        #setup test users
        userEmails = [
            "*****@*****.**", "*****@*****.**", "*****@*****.**",
            "*****@*****.**", "*****@*****.**",
            test_users["admin_email"], test_users["approved_email"],
            "*****@*****.**"
        ]
        userStatus = [
            "awaiting_confirmation", "email_confirmed", "awaiting_approval",
            "awaiting_approval", "awaiting_approval", "approved", "approved",
            "denied"
        ]
        userPermissions = [
            0, AccountType.AGENCY_USER, AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER,
            AccountType.WEBSITE_ADMIN + AccountType.AGENCY_USER,
            AccountType.AGENCY_USER, AccountType.AGENCY_USER
        ]

        # Add new users
        userDb = UserHandler()
        userDb.createUserWithPassword(test_users["submission_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["change_user_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["password_reset_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["inactive_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users["password_lock_email"],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users['expired_lock_email'],
                                      user_password, Bcrypt())
        userDb.createUserWithPassword(test_users['agency_admin_email'],
                                      admin_password,
                                      Bcrypt(),
                                      permission=4)
        userDb.createUserWithPassword(test_users['agency_user'], user_password,
                                      Bcrypt())

        # Set the Agency for the agency user
        agencyUser = userDb.getUserByEmail(test_users['agency_user'])
        userDb.session.commit()
        cls.agency_user_id = agencyUser.user_id

        # Set the specified account to be expired
        expiredUser = userDb.getUserByEmail(test_users['expired_lock_email'])
        today = parse(time.strftime("%c"))
        expiredUser.last_login_date = (today -
                                       timedelta(days=120)).strftime("%c")
        userDb.session.commit()

        # Create users for status testing
        for index in range(len(userEmails)):
            email = userEmails[index]
            userDb.addUnconfirmedEmail(email)
            user = userDb.getUserByEmail(email)
            userDb.changeStatus(user, userStatus[index])
            userDb.setPermission(user, userPermissions[index])

        #set up approved user
        user = userDb.getUserByEmail(test_users['approved_email'])
        user.username = "******"
        userDb.setPassword(user, user_password, Bcrypt())
        cls.approved_user_id = user.user_id

        #set up admin user
        admin = userDb.getUserByEmail(test_users['admin_email'])
        userDb.setPassword(admin, admin_password, Bcrypt())
        admin.name = "Mr. Manager"
        admin.cgac_code = "SYS"
        userDb.session.commit()

        #set up status changed user
        statusChangedUser = userDb.getUserByEmail(
            test_users["change_user_email"])
        cls.status_change_user_id = statusChangedUser.user_id
        statusChangedUser.name = "Test User"
        statusChangedUser.user_status_id = userDb.getUserStatusId(
            "email_confirmed")
        userDb.session.commit()

        #set up deactivated user
        user = userDb.getUserByEmail(test_users["inactive_email"])
        user.last_login_date = time.strftime("%c")
        user.is_active = False
        userDb.session.commit()

        #set up info needed by the individual test classes
        cls.test_users = test_users
        cls.user_password = user_password
        cls.admin_password = admin_password
        cls.interfaces = InterfaceHolder()
        cls.jobTracker = cls.interfaces.jobDb
        cls.errorDatabase = cls.interfaces.errorDb
        cls.userDb = cls.interfaces.userDb
        cls.local = CONFIG_BROKER['local']