Beispiel #1
0
def test_activate_user(database):
    """Test creating inactive users and activating them."""
    # -- Test creating an inactive user ---------------------------------------
    username = '******'
    password = '******'
    with database.session() as session:
        users = UserManager(session)
        user = users.register_user(username, password, verify=True)
        user_id = user.user_id
        # Attempt to login will raise error
        with pytest.raises(err.UnknownUserError):
            users.login_user(username, password)
    # -- Test activate user ---------------------------------------------------
    with database.session() as session:
        # After activating the user login should succeed.
        users = UserManager(session)
        auth = OpenAccessAuth(session)
        active_user = users.activate_user(user_id)
        assert active_user.user_id == user_id
        assert active_user.name == username
        assert active_user.api_key is None
        user = users.login_user(username, password)
        assert user.name == username
        assert user.api_key is not None
        assert auth.authenticate(user.api_key.value).user_id == user_id
        # Activate the same user twice should not raise an error
        active_user = users.activate_user(user_id)
        assert active_user.user_id == user_id
        assert active_user.name == username
        assert active_user.api_key is not None
def test_user_handle_serialization(database):
    """Test serialization of user handles."""
    schema = validator('User')
    view = UserSerializer()
    with database.session() as session:
        manager = UserManager(session)
        user = manager.register_user('alice', 'mypwd')
        doc = view.user(user)
        schema.validate(doc)
        assert doc[labels.USER_NAME] == 'alice'
        assert labels.USER_TOKEN not in doc
        user = manager.login_user('alice', 'mypwd')
        doc = view.user(user, include_token=True)
        schema.validate(doc)
        assert doc[labels.USER_NAME] == 'alice'
        assert labels.USER_TOKEN in doc
Beispiel #3
0
def test_login_after_timeout(database, authcls):
    """Test login after key expired."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with a single active user.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
    # Test login after timeout -----------------------------------------
    with database.session() as session:
        # Create user manager with TTL for login tokens of 1 sec.
        users = UserManager(session, token_timeout=1)
        # Authenticate user 1. Then sleep for 1.5 sec. When logging in again an
        # new api-key is generated.
        api_key = users.login_user(user_1, user_1).api_key.value
        time.sleep(1.5)
        assert users.login_user(user_1, user_1).api_key.value != api_key
Beispiel #4
0
def test_authenticate_after_timeout(database, authcls):
    """Test authentication after key expired."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with a single active user.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
    # Test authenticate after timeout -----------------------------------------
    with database.session() as session:
        # Create user manager with TTL for login tokens of 1 sec.
        users = UserManager(session, token_timeout=1)
        auth = authcls(session)
        # Authenticate user 1. Then sleep for 1.5 sec. Trying to authenticate
        # the user after the sleep period should raise an error.
        api_key = users.login_user(user_1, user_1).api_key.value
        time.sleep(1.5)
        with pytest.raises(err.UnauthenticatedAccessError):
            auth.authenticate(api_key)
def test_user_listing_serialization(database):
    """Test serialization of user listings."""
    schema = validator('UserListing')
    view = UserSerializer()
    with database.session() as session:
        manager = UserManager(session)
        manager.register_user('alice', 'mypwd')
        manager.register_user('bob', 'mypwd')
        doc = view.user_listing(manager.list_users())
        schema.validate(doc)
        assert len(doc[labels.USER_LIST]) == 2
Beispiel #6
0
def test_reset_request_timeout(database):
    """Test resetting a user password using a request identifier that has
    timed out.
    """
    # -- Setup ----------------------------------------------------------------
    #
    # Create database with single active user.
    username = '******'
    with database.session() as session:
        users = UserManager(session)
        users.register_user(username, 'pwd1')
    # -- Test password reset after timed-out ----------------------------------
    with database.session() as session:
        # Request a password reset and then sleep for a period of time that is
        # lonker than the token timeout period.
        users = UserManager(session, token_timeout=1)
        request_id = users.request_password_reset(username)
        time.sleep(2)
        with pytest.raises(err.UnknownRequestError):
            users.reset_password(request_id=request_id, password='******')
Beispiel #7
0
    def __init__(self, session: Session, fs: FileStore, users: Optional[UserManager] = None):
        """Initialize the connection to the underlying database and the file
        system helper to access group files.

        Parameters
        ----------
        session: sqlalchemy.orm.session.Session
            Database session.
        fs: flowserv.model.files.FileStore
            File store for uploaded group files.
        users: flowserv.model.user.UserManager, default=None
            Manager to access user objects.
        """
        self.session = session
        self.fs = fs
        self.users = users if users is not None else UserManager(session=session)
Beispiel #8
0
 def __enter__(self) -> API:
     """Create a new instance of the local API when the context manager is
     entered.
     """
     # Open a new database session.
     self._session = self._db.session()
     session = self._session.open()
     # Shortcuts for local variables.
     env = self._env
     fs = self._fs
     engine = self._engine
     # Start by creating the authorization component and setting the
     # identifier for and authenticated user.
     user_id = self._user_id
     username = None
     if env[AUTH] == config.AUTH_OPEN:
         auth = OpenAccessAuth(session)
         user_id = config.DEFAULT_USER if user_id is None else user_id
     else:
         auth = DefaultAuthPolicy(session)
         access_token = self._access_token if self._access_token is not None else env.get(
             ACCESS_TOKEN)
         if access_token and user_id is None:
             # If an access token is given we retrieve the user that is
             # associated with the token. Authentication may raise an error.
             # Here, we ignore that error since the token may be an outdated
             # token that is stored in the environment.
             try:
                 user = auth.authenticate(access_token)
                 # Set the user name for the authenticated user (to be
                 # included in the service descriptor).
                 username = user.name
                 user_id = user.user_id
             except err.UnauthenticatedAccessError:
                 pass
     # Create the individual components of the API.
     ttl = env.get(config.FLOWSERV_AUTH_LOGINTTL, config.DEFAULT_LOGINTTL)
     user_manager = UserManager(session=session, token_timeout=ttl)
     run_manager = RunManager(session=session, fs=fs)
     group_manager = WorkflowGroupManager(session=session,
                                          fs=fs,
                                          users=user_manager)
     ranking_manager = RankingManager(session=session)
     workflow_repo = WorkflowManager(session=session, fs=fs)
     return API(
         service=ServiceDescriptor.from_config(env=env, username=username),
         workflow_service=LocalWorkflowService(
             workflow_repo=workflow_repo,
             ranking_manager=ranking_manager,
             group_manager=group_manager,
             run_manager=run_manager,
             user_id=user_id),
         group_service=LocalWorkflowGroupService(
             group_manager=group_manager,
             workflow_repo=workflow_repo,
             backend=engine,
             run_manager=run_manager,
             auth=auth,
             user_id=user_id),
         upload_service=LocalUploadFileService(group_manager=group_manager,
                                               auth=auth,
                                               user_id=user_id),
         run_service=LocalRunService(run_manager=run_manager,
                                     group_manager=group_manager,
                                     ranking_manager=ranking_manager,
                                     backend=engine,
                                     auth=auth,
                                     user_id=user_id),
         user_service=LocalUserService(manager=user_manager, auth=auth))
Beispiel #9
0
def test_authenticate_user(database, authcls):
    """Test user login and logout. Uses a database with two active and one
    inactive user to validate that active users can login and logout while
    inactive users cannot login.
    """
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with two active and one inactive users.
    with database.session() as session:
        user_1 = model.create_user(session, active=True)
        user_2 = model.create_user(session, active=True)
        user_3 = model.create_user(session, active=False)
    # -- Test login -----------------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        token_1 = users.login_user(user_1, user_1).api_key.value
        token_2 = users.login_user(user_2, user_2).api_key.value
    # -- Test authentication --------------------------------------------------
    with database.session() as session:
        auth = authcls(session)
        # Authentication of logged-in users using the API key should return the
        # respective user identifier.
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_2).user_id == user_2
    # -- Test logout ----------------------------------------------------------
    with database.session() as session:
        # Logout user 1. User 2 should still be able to authenticate while a
        # user that is logged out cannot.
        users = UserManager(session)
        auth = authcls(session)
        assert users.logout_user(token_1).user_id == user_1
        # Authenticating user 1 will raise exception.
        with pytest.raises(err.UnauthenticatedAccessError):
            auth.authenticate(token_1)
        # Logging out a user that is not logged in will not raise error>
        assert users.logout_user(token_1) is None
        # User 2 can still authenticate.
        assert auth.authenticate(token_2).user_id == user_2
    # -- Test re-login --------------------------------------------------------
    with database.session() as session:
        # Login user 1 again.
        users = UserManager(session)
        auth = authcls(session)
        token_1 = users.login_user(user_1, user_1).api_key.value
        # User 1 and 2 can now be authenticated again.
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_2).user_id == user_2
        # If a logged in user logs in the previous key does not become invalid.
        token_3 = users.login_user(user_1, user_1).api_key.value
        assert auth.authenticate(token_1).user_id == user_1
        assert auth.authenticate(token_3).user_id == user_1
    # -- Error cases ----------------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        auth = authcls(session)
        # Attempt to authenticate unknown user raises error
        with pytest.raises(err.UnknownUserError):
            users.login_user('unknown', user_1)
        # Attempt to authenticate with invalid password will raises error
        with pytest.raises(err.UnknownUserError):
            users.login_user(user_1, user_2)
        # Inactive user 3 should not be able to login.
        with pytest.raises(err.UnknownUserError):
            users.login_user(user_3, user_3)
        # An error is raised when using an invalid API key.
        with pytest.raises(err.UnauthenticatedAccessError):
            assert auth.authenticate('UNKNOWN')
Beispiel #10
0
def test_register_user(database):
    """Test registering a new user."""
    # -- Test creating an active user -----------------------------------------
    with database.session() as session:
        users = UserManager(session)
        auth = OpenAccessAuth(session)
        reg_user = users.register_user('*****@*****.**', 'pwd1')
        assert reg_user.api_key is None
        user_1 = users.login_user('*****@*****.**', 'pwd1')
        assert user_1.name == '*****@*****.**'
        user_id_1 = auth.authenticate(user_1.api_key.value).user_id
        assert user_1.user_id == user_id_1
    # -- Error cases ----------------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        # Register user with existing email address raises error
        with pytest.raises(err.DuplicateUserError):
            users.register_user('*****@*****.**', 'pwd1')
        # Providing invalid email or password will raise error
        with pytest.raises(err.ConstraintViolationError):
            users.register_user(None, 'pwd1')
        with pytest.raises(err.ConstraintViolationError):
            users.register_user(' \t', 'pwd1')
        with pytest.raises(err.ConstraintViolationError):
            users.register_user('a' * 513, 'pwd1')
        with pytest.raises(err.ConstraintViolationError):
            users.register_user('*****@*****.**', ' ')
Beispiel #11
0
def test_list_users(database):
    """Test listing and searching for users."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create a database with four active and one inactive user.
    with database.session() as session:
        users = UserManager(session)
        users.register_user('*****@*****.**', 'pwd1', verify=False)
        users.register_user('*****@*****.**', 'pwd1', verify=False)
        users.register_user('*****@*****.**', 'pwd1', verify=False)
        users.register_user('*****@*****.**', 'pwd1', verify=False)
        u = users.register_user('*****@*****.**', 'pwd1', verify=True)
        inactive_user_id = u.user_id
    # -- Test user listing ----------------------------------------------------
    with database.session() as session:
        # There should be four users in the returned list.
        users = UserManager(session)
        assert len(users.list_users()) == 4
    with database.session() as session:
        # After activating the inactive user, the listing contains five users.
        users = UserManager(session)
        users.activate_user(inactive_user_id)
        assert len(users.list_users()) == 5
    # -- Test query prefixes --------------------------------------------------
    with database.session() as session:
        # Query users by name prefix.
        users = UserManager(session)
        assert len(users.list_users(prefix='a')) == 3
        assert len(users.list_users(prefix='ab')) == 2
        assert len(users.list_users(prefix='ade')) == 1
Beispiel #12
0
def test_reset_password(database):
    """Test resetting a user password."""
    # -- Setup ----------------------------------------------------------------
    #
    # Create one active user.
    username = '******'
    password = '******'
    with database.session() as session:
        # After a reset request has been send the previous password should
        # still be valid.
        users = UserManager(session)
        auth = OpenAccessAuth(session)
        user_id = users.register_user(username, password).user_id
    # -- Test reset password --------------------------------------------------
    with database.session() as session:
        users = UserManager(session)
        auth = OpenAccessAuth(session)
        # Ensure login works prior to reset request.
        token = users.login_user(username, password).api_key.value
        assert auth.authenticate(token).user_id == user_id
        request_id = users.request_password_reset(username)
        password = '******'
        user = users.reset_password(request_id=request_id, password=password)
        assert user.user_id == user_id
        # After resetting the password the previous API key for the user is
        # invalid
        with pytest.raises(err.UnauthenticatedAccessError):
            auth.authenticate(token)
        token = users.login_user('*****@*****.**', 'mypwd').api_key.value
        assert auth.authenticate(token).user_id == user_id
    # -- Test login after request ---------------------------------------------
    with database.session() as session:
        # After a reset request has been send the previous password should
        # still be valid.
        users = UserManager(session)
        auth = OpenAccessAuth(session)
        users.request_password_reset(username)
        token = users.login_user(username, password).api_key.value
        assert auth.authenticate(token).user_id == user_id
    # -- Test request reset for unknown user ----------------------------------
    with database.session() as session:
        users = UserManager(session)
        assert users.request_password_reset('*****@*****.**') is not None
    # --Error cases -----------------------------------------------------------
    with database.session() as session:
        # An error is raised when (i) trying to use a request for an unknown
        # user, (ii) a previously completed reset request, or (iii) an unknown
        # request identifier to reset a user password
        users = UserManager(session)
        with pytest.raises(err.UnknownRequestError):
            users.reset_password(request_id=request_id, password=password)
        with pytest.raises(err.UnknownRequestError):
            users.reset_password(request_id='UNKNOWN', password=password)
        with pytest.raises(err.UnknownRequestError):
            users.reset_password(request_id='unknown', password=password)