Exemple #1
0
def shib_sp_login():
    """The request from shibboleth sp.

    :return: confirm page when relation is empty
    """
    try:
        if not current_app.config['SHIB_ACCOUNTS_LOGIN_ENABLED']:
            return url_for_security('login')
        shib_session_id = request.form.get('SHIB_ATTR_SESSION_ID', None)
        if shib_session_id is None or len(shib_session_id) == 0:
            return url_for_security('login')
        shib_attr, error = parse_attributes()
        if error:
            return url_for_security('login')
        datastore = RedisStore(
            redis.StrictRedis.from_url(current_app.config['CACHE_REDIS_URL']))
        ttl_sec = int(current_app.config['SHIB_ACCOUNTS_LOGIN_CACHE_TTL'])
        datastore.put(config.SHIB_CACHE_PREFIX + shib_session_id,
                      bytes(json.dumps(shib_attr), encoding='utf-8'),
                      ttl_secs=ttl_sec)
        shib_user = ShibUser(shib_attr)
        rst = shib_user.get_relation_info()
        """ check the relation of shibboleth user with weko account"""
        next_url = 'weko_accounts.shib_auto_login'
        if rst is None:
            """relation is not existed, cache shibboleth info to redis."""
            next_url = 'weko_accounts.shib_login'
        query_string = {
            'SHIB_ATTR_SESSION_ID': shib_session_id,
            '_method': 'GET'
        }
        return url_for(next_url, **query_string)
    except BaseException:
        current_app.logger.error('Unexpected error: ', sys.exc_info()[0])
    return url_for_security('login')
def test_view_list_sessions(app):
    """Test view list sessions."""
    with app.test_request_context():
        user1 = create_test_user(email="*****@*****.**")
        user2 = create_test_user(email="*****@*****.**")

    with app.test_client() as client:
        client.post(
            url_for_security("login"),
            data=dict(
                email=user1.email,
                password=user1.password_plaintext,
            ),
        )

    with app.test_client() as client:
        client.post(
            url_for_security("login"),
            data=dict(
                email=user2.email,
                password=user2.password_plaintext,
            ),
        )

        # get the list of user 2 sessions
        url = url_for("invenio_accounts.security")
        res = client.get(url)
        assert res.status_code == 200

        # check session for user 1 is not in the list
        sessions_1 = SessionActivity.query.filter_by(user_id=user1.id).all()
        assert len(sessions_1) == 1
        assert sessions_1[0].sid_s not in res.data.decode("utf-8")

        # check session for user 2 is in the list
        sessions_2 = SessionActivity.query.filter_by(user_id=user2.id).all()
        assert len(sessions_2) == 1
        assert sessions_2[0].sid_s in res.data.decode("utf-8")

        # test user 2 to delete user 1 session
        url = url_for("invenio_accounts.revoke_session")
        res = client.post(url, data={"sid_s": sessions_1[0].sid_s})
        assert res.status_code == 302
        assert (
            SessionActivity.query.filter_by(
                user_id=user1.id, sid_s=sessions_1[0].sid_s
            ).count()
            == 1
        )

        # test user 2 to delete user 1 session
        url = url_for("invenio_accounts.revoke_session")
        res = client.post(url, data={"sid_s": sessions_2[0].sid_s})
        assert res.status_code == 302
        assert (
            SessionActivity.query.filter_by(
                user_id=user1.id, sid_s=sessions_2[0].sid_s
            ).count()
            == 0
        )
Exemple #3
0
def shib_login():
    """Get shibboleth user login page.

    :return: confirm user page when relation is empty
    """
    try:
        shib_session_id = request.args.get('SHIB_ATTR_SESSION_ID', None)
        if shib_session_id is None or len(shib_session_id) == 0:
            return redirect(url_for_security('login'))
        datastore = RedisStore(
            redis.StrictRedis.from_url(current_app.config['CACHE_REDIS_URL']))
        cache_key = config.SHIB_CACHE_PREFIX + shib_session_id
        if not datastore.redis.exists(cache_key):
            return redirect(url_for_security('login'))
        cache_val = datastore.get(cache_key)
        if cache_val is None:
            datastore.delete(cache_key)
            return redirect(url_for_security('login'))
        cache_val = json.loads(str(cache_val, encoding='utf-8'))
        session['shib_session_id'] = shib_session_id
        csrf_random = generate_random_str(length=64)
        session['csrf_random'] = csrf_random
        return render_template(config.WEKO_ACCOUNTS_CONFIRM_USER_TEMPLATE,
                               csrf_random=csrf_random,
                               email=cache_val['shib_mail']
                               if len(cache_val['shib_mail']) > 0 else '')
    except BaseException:
        current_app.logger.error('Unexpected error: ', sys.exc_info()[0])
    return abort(400)
Exemple #4
0
def shib_auto_login():
    """Create new account and auto login when shibboleth user first login.

    :return: next url
    """
    try:
        is_auto_bind = False
        shib_session_id = request.args.get('SHIB_ATTR_SESSION_ID', None)
        if shib_session_id is None:
            shib_session_id = session['shib_session_id']
            is_auto_bind = True
        if shib_session_id is None or len(shib_session_id) == 0:
            return redirect(url_for_security('login'))
        datastore = RedisStore(
            redis.StrictRedis.from_url(current_app.config['CACHE_REDIS_URL']))
        cache_key = config.SHIB_CACHE_PREFIX + shib_session_id
        if not datastore.redis.exists(cache_key):
            return redirect(url_for_security('login'))
        cache_val = datastore.get(cache_key)
        if cache_val is None:
            datastore.delete(cache_key)
            return redirect(url_for_security('login'))
        cache_val = json.loads(str(cache_val, encoding='utf-8'))
        shib_user = ShibUser(cache_val)
        if not is_auto_bind:
            shib_user.get_relation_info()
        else:
            shib_user.new_relation_info()
        if shib_user.shib_user is not None:
            shib_user.shib_user_login()
        datastore.delete(cache_key)
        return redirect(session['next'] if 'next' in session else '/')
    except BaseException:
        current_app.logger.error('Unexpected error: ', sys.exc_info()[0])
    return abort(400)
Exemple #5
0
def test_read_metadata(client, superuser, admin, moderator, submitter, user,
                       document_with_file):
    """Test read files permissions."""

    users = [superuser, admin, moderator, submitter, user, None]
    url_files = url_for('invenio_records_files.doc_bucket_api',
                        pid_value=document_with_file.get('pid'))
    for u, status in zip(users, [200, 200, 200, 200, 200, 200]):
        if u:
            login_user_via_session(client, email=u['email'])
        else:
            client.get(url_for_security('logout'))
        res = client.get(url_files)
        assert res.status_code == status

    # Masked document
    document_with_file['masked'] = 'masked_for_all'
    document_with_file.commit()
    for u, status in zip(users, [200, 200, 200, 404, 404, 404]):
        if u:
            login_user_via_session(client, email=u['email'])
        else:
            client.get(url_for_security('logout'))
        res = client.get(url_files)
        assert res.status_code == status
Exemple #6
0
    def test_login(self):
        zero = User.query.count()
        self.assertEqual(0, zero)
        self.client.post(url_for_security('login'),
                         data={
                             'email': '*****@*****.**',
                             'password': '******'
                         })
        self.assertTrue(current_user.is_anonymous)

        self.client.post(url_for_security('register'),
                         data={
                             'email': '*****@*****.**',
                             'password': '******',
                             'password_confirm': 'test123'
                         })
        cnt = User.query.count()
        self.assertEqual(1, cnt)

        self.client.get(url_for_security('logout'))

        with self.client:
            it = self.client.post(url_for_security('login'),
                                  data={
                                      'email': '*****@*****.**',
                                      'password': '******'
                                  })
            t = current_user
            self.assertIsNotNone(t)
            self.assertEqual('*****@*****.**', t.email)
Exemple #7
0
def test_client_authenticated(app):
    """Test for testutils.py:client_authenticated(client).

    We want to verify that it doesn't return True when the client isn't
    authenticated/logged in."""
    ext = InvenioAccounts(app)
    # Required for the test app/templates
    app.register_blueprint(blueprint)

    email = '*****@*****.**'
    password = '******'

    with app.app_context():
        change_password_url = url_for_security('change_password')
        login_url = url_for_security('login')

    with app.test_client() as client:
        # At this point we should not be authenticated/logged in as a user
        assert flask_login.current_user.is_anonymous
        assert not testutils.client_authenticated(client,
                                                  test_url=change_password_url)

        # Test HTTP status code of view when not logged in.
        response = client.get(change_password_url)
        assert response.status_code == 302
        assert change_password_url not in response.location
        assert login_url in response.location

        # Once more, following redirects.
        response = client.get(change_password_url, follow_redirects=True)
        assert response.status_code == 200
        assert response.location is None

        # Create a user manually directly in the datastore
        ext.datastore.create_user(email=email,
                                  password=encrypt_password(password))
        db.session.commit()

        # Manual login via view
        response = client.post(login_url,
                               data={
                                   'email': email,
                                   'password': password
                               },
                               environ_base={'REMOTE_ADDR': '127.0.0.1'})

        # Client gets redirected after logging in
        assert response.status_code == 302
        assert testutils.client_authenticated(client)
        assert flask_login.current_user.is_authenticated
        # `is_authenticated` returns True as long as the user object
        # isn't anonymous, i.e. it's an actual user.

        response = client.get(change_password_url)
        assert response.status_code == 200
        response = client.get(change_password_url, follow_redirects=True)
        assert response.status_code == 200
Exemple #8
0
 def test_unique_user_username(self):
     data = dict(username='******',
                 email='*****@*****.**',
                 password='******',
                 password_confirm='password')
     self.client.post(url_for_security('register'), data=data)
     response = self.client.post(url_for_security('register'), data=data)
     self.assertIn('Username already taken',
                   response.data.decode(response.charset))
def test_client_authenticated(app):
    """Test for testutils.py:client_authenticated(client).

    We want to verify that it doesn't return True when the client isn't
    authenticated/logged in.
    """
    ds = app.extensions["security"].datastore
    email = "*****@*****.**"
    password = "******"

    with app.app_context():
        change_password_url = url_for_security("change_password")
        login_url = url_for_security("login")

        with app.test_client() as client:
            # At this point we should not be authenticated/logged in as a user
            # assert flask_login.current_user.is_anonymous
            assert not testutils.client_authenticated(
                client, test_url=change_password_url)

            # Test HTTP status code of view when not logged in.
            response = client.get(change_password_url)
            assert response.status_code == 302
            assert change_password_url not in response.location
            assert login_url in response.location

            # Once more, following redirects.
            response = client.get(change_password_url, follow_redirects=True)
            assert response.status_code == 200
            assert response.location is None

            # Create a user manually directly in the datastore
            ds.create_user(email=email, password=hash_password(password))
            db.session.commit()

            # Manual login via view
            response = client.post(
                login_url,
                data={
                    "email": email,
                    "password": password
                },
                environ_base={"REMOTE_ADDR": "127.0.0.1"},
            )

            # Client gets redirected after logging in
            assert response.status_code == 302
            assert testutils.client_authenticated(client)
            assert flask_login.current_user.is_authenticated
            # `is_authenticated` returns True as long as the user object
            # isn't anonymous, i.e. it's an actual user.

            response = client.get(change_password_url)
            assert response.status_code == 200
            response = client.get(change_password_url, follow_redirects=True)
            assert response.status_code == 200
def test_client_authenticated(app):
    """Test for testutils.py:client_authenticated(client).

    We want to verify that it doesn't return True when the client isn't
    authenticated/logged in."""
    ext = InvenioAccounts(app)
    # Required for the test app/templates
    app.register_blueprint(blueprint)

    email = '*****@*****.**'
    password = '******'

    with app.app_context():
        change_password_url = url_for_security('change_password')
        login_url = url_for_security('login')

    with app.test_client() as client:
        # At this point we should not be authenticated/logged in as a user
        assert flask_login.current_user.is_anonymous
        assert not testutils.client_authenticated(
            client, test_url=change_password_url)

        # Test HTTP status code of view when not logged in.
        response = client.get(change_password_url)
        assert response.status_code == 302
        assert change_password_url not in response.location
        assert login_url in response.location

        # Once more, following redirects.
        response = client.get(change_password_url, follow_redirects=True)
        assert response.status_code == 200
        assert response.location is None

        # Create a user manually directly in the datastore
        ext.datastore.create_user(email=email,
                                  password=encrypt_password(password))
        db.session.commit()

        # Manual login via view
        response = client.post(login_url,
                               data={'email': email, 'password': password},
                               environ_base={'REMOTE_ADDR': '127.0.0.1'})

        # Client gets redirected after logging in
        assert response.status_code == 302
        assert testutils.client_authenticated(client)
        assert flask_login.current_user.is_authenticated
        # `is_authenticated` returns True as long as the user object
        # isn't anonymous, i.e. it's an actual user.

        response = client.get(change_password_url)
        assert response.status_code == 200
        response = client.get(change_password_url, follow_redirects=True)
        assert response.status_code == 200
Exemple #11
0
 def test_unique_user_username(self):
     data = dict(
         username="******",
         email="*****@*****.**",
         password="******",
         password_confirm="password",
     )
     self.client.post(url_for_security("register"), data=data)
     response = self.client.post(url_for_security("register"), data=data)
     self.assertIn("Username already taken",
                   response.data.decode(response.charset))
Exemple #12
0
def test_clean_session_table(task_app):
    """Test clean session table."""
    # set session lifetime
    task_app.permanent_session_lifetime = timedelta(seconds=20)

    # protected page
    @task_app.route("/test", methods=["GET"])
    @login_required
    def test():
        return "test"

    with task_app.test_request_context():
        user1 = create_test_user(email="*****@*****.**")
        user2 = create_test_user(email="*****@*****.**")

        with task_app.test_client() as client:
            client.post(
                url_for_security("login"),
                data=dict(
                    email=user1.email,
                    password=user1.password_plaintext,
                ),
            )
        assert len(SessionActivity.query.all()) == 1
        sleep(15)

        with task_app.test_client() as client:
            client.post(
                url_for_security("login"),
                data=dict(
                    email=user2.email,
                    password=user2.password_plaintext,
                ),
            )
            assert len(SessionActivity.query.all()) == 2
            sleep(10)

            clean_session_table.s().apply()
            assert len(SessionActivity.query.all()) == 1

            protected_url = url_for("test")

            res = client.get(protected_url)
            assert res.status_code == 200

            sleep(15)
            clean_session_table.s().apply()
            assert len(SessionActivity.query.all()) == 0

            res = client.get(protected_url)
            # check if the user is really logout
            assert res.status_code == 302
def test_view_list_sessions(app, app_i18n):
    """Test view list sessions."""
    with app.test_request_context():
        user1 = create_test_user(email='*****@*****.**')
        user2 = create_test_user(email='*****@*****.**')

        with app.test_client() as client:
            client.post(url_for_security('login'), data=dict(
                email=user1.email,
                password=user1.password_plaintext,
            ))

        with app.test_client() as client:
            client.post(url_for_security('login'), data=dict(
                email=user2.email,
                password=user2.password_plaintext,
            ))

            # get the list of user 2 sessions
            url = url_for('invenio_accounts.security')
            res = client.get(url)
            assert res.status_code == 200

            # check session for user 1 is not in the list
            sessions_1 = SessionActivity.query.filter_by(
                user_id=user1.id).all()
            assert len(sessions_1) == 1
            assert sessions_1[0].sid_s not in res.data.decode('utf-8')

            # check session for user 2 is in the list
            sessions_2 = SessionActivity.query.filter_by(
                user_id=user2.id).all()
            assert len(sessions_2) == 1
            assert sessions_2[0].sid_s in res.data.decode('utf-8')

            # test user 2 to delete user 1 session
            url = url_for('invenio_accounts.revoke_session')
            res = client.post(url, data={'sid_s': sessions_1[0].sid_s})
            assert res.status_code == 302
            assert SessionActivity.query.filter_by(
                user_id=user1.id, sid_s=sessions_1[0].sid_s).count() == 1

            # test user 2 to delete user 1 session
            url = url_for('invenio_accounts.revoke_session')
            res = client.post(url, data={'sid_s': sessions_2[0].sid_s})
            assert res.status_code == 302
            assert SessionActivity.query.filter_by(
                user_id=user1.id, sid_s=sessions_2[0].sid_s).count() == 0
def test_by_reference_validation(api, users, location, es, data,
                                 fields_with_errors, fields_without_errors):
    with api.test_request_context(), api.test_client() as client:
        client.post(
            url_for_security("login"),
            data={
                "email": users[0]["email"],
                "password": "******"
            },
        )

        response = client.post(
            "/sword/service-document",
            data=json.dumps(data),
            headers={
                "Content-Disposition": "attachment; by-reference=true",
                "Content-Type": "application/ld+json",
            },
        )
        assert response.status_code == HTTPStatus.BAD_REQUEST
        assert response.is_json
        assert response.json["@type"] == "ValidationFailed"
        # The fields with errors are the superset of the ones we expected; i.e. it shouldn't accept data we
        # in this test know is wrong
        print(response.json)
        assert set(response.json["errors"]) >= set(fields_with_errors)
        # We know these fields to be good
        assert not (set(response.json["errors"]) & set(fields_without_errors))
Exemple #15
0
def _create_new_record_version(app):
    """Create a new version of a record existing before the upgrade."""
    from invenio_accounts.models import User
    from flask_security import url_for_security
    from flask_security.utils import hash_password
    from flask import url_for
    from invenio_oauth2server.models import Token
    user = User.query.filter(User.email=='*****@*****.**').one()
    user.password = hash_password('123')
    token = Token.create_personal(
        'other_token', user.id,
        scopes=[]
    )
    headers = [
        ('Authorization', 'Bearer {}'.format(token.access_token)),
        ('Content-type', 'application/json')
    ]
    db.session.commit()
    with app.test_request_context():
        login_url = url_for_security('login')
    with app.test_client() as client:
        res = client.post(login_url, data={
            'email': '*****@*****.**', 'password': '******'
        })
        assert res.status_code == 302
        url = url_for('b2share_records_rest.b2rec_list',
                      version_of='1033083fedf4408fb5611f23527a926d')
        res = client.post(url, headers=headers)
        assert res.status_code == 201
def test_repeated_login_session_population(app):
    """Verify session population on repeated login.

    Check that the number of SessionActivity entries match the number of
    sessions in the kv-store, when logging in with one user.
    """
    with app.app_context():
        user = testutils.create_test_user()
        query = db.session.query(SessionActivity)
        assert query.count() == len(app.kvsession_store.keys())

        with app.test_client() as client:
            # After logging in, there should be one session in the kv-store and
            # one SessionActivity
            testutils.login_user_via_view(client, user=user)
            assert testutils.client_authenticated(client)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert query.count() == len(app.kvsession_store.keys())

            # Sessions are not deleted upon logout
            client.get(flask_security.url_for_security('logout'))
            assert len(app.kvsession_store.keys()) == 1
            query = db.session.query(SessionActivity)
            assert query.count() == len(app.kvsession_store.keys())

            # After logging out and back in, the number of sessions correspond
            # to the number of SessionActivity entries.
            testutils.login_user_via_view(client, user=user)
            query = db.session.query(SessionActivity)
            assert query.count() == len(app.kvsession_store.keys())
Exemple #17
0
def test_repeated_login_session_population(app):
    """Verify session population on repeated login."""
    with app.app_context():
        user = testutils.create_test_user('*****@*****.**')
        query = db.session.query(SessionActivity)
        assert query.count() == len(app.kvsession_store.keys())

        with app.test_client() as client:
            # After logging in, there should be one session in the kv-store and
            # one SessionActivity
            testutils.login_user_via_view(client, user=user)
            assert testutils.client_authenticated(client)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            first_login_session_id = app.kvsession_store.keys()[0]

            # Sessions are not deleted upon logout
            client.get(flask_security.url_for_security('logout'))
            assert len(app.kvsession_store.keys()) == 1
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            # Session id doesn't change after logout
            assert first_login_session_id == app.kvsession_store.keys()[0]

            # After logging out and back in, the inital session id in the
            # sessionstore should be updated, and there should be two
            # SessionActivity entries (the old one and the regenerated).
            testutils.login_user_via_view(client, user=user)
            query = db.session.query(SessionActivity)
            assert query.count() == 2
            assert len(app.kvsession_store.keys()) == 1
            assert first_login_session_id != app.kvsession_store.keys()[0]
def test_repeated_login_session_population(app):
    """Verify that the number of SessionActivity entries match the number of
    sessions in the kv-store, when logging in with one user."""
    InvenioAccounts(app)
    app.register_blueprint(blueprint)

    user = testutils.create_test_user()
    query = _datastore.db.session.query(SessionActivity)
    assert query.count() == len(testutils.get_kvsession_keys())

    with app.test_client() as client:
        # After logging in, there should be one session in the kv-store and
        # one SessionActivity
        testutils.login_user_via_view(client, user=user)
        assert testutils.client_authenticated(client)
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == 1
        assert query.count() == len(testutils.get_kvsession_keys())

        # Sessions are not deleted upon logout
        client.get(flask_security.url_for_security('logout'))
        assert len(testutils.get_kvsession_keys()) == 1
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == len(testutils.get_kvsession_keys())

        # After logging out and back in, the number of sessions correspond to
        # the number of SessionActivity entries.
        testutils.login_user_via_view(client, user=user)
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == len(testutils.get_kvsession_keys())
Exemple #19
0
    def test_change_thumbnail(self):
        file = (io.BytesIO(b"abcdef"), 'test.jpg')

        api_utils.post(url_for_security('login'),
                       data={
                           'email': '*****@*****.**',
                           'password': '******'
                       },
                       headers={'Authentication-Token': self.token})

        bookmark = BookMark(url='dummy.url', img='dummy.png')

        past_img = bookmark.img

        self.current_user.bookmarks.append(bookmark)

        db.session.add(self.current_user)
        db.session.commit()

        data = {'img': file, 'id': BookMark.query.first().id}
        res = self.client.patch(url_for('library.change_thumbnail'),
                                data=data,
                                headers={
                                    'Authentication-Token': self.token,
                                    'Content-Type': 'multipart/form-data'
                                })

        self.assertNotEqual(past_img, bookmark.img)

        path = Path(app.config['STORAGE_PATH'] + '/' + bookmark.img)
        self.assertTrue(path.is_file())
        self.assertStatus(res, 204)
def login(test_client, email='*****@*****.**', password='******'):
    return test_client.post(
        url_for_security('login'),
        data={
            'email': email,
            'password': password,
        })
Exemple #21
0
def test_repeated_login_session_population(app):
    """Verify session population on repeated login.

    Check that the number of SessionActivity entries match the number of
    sessions in the kv-store, when logging in with one user.
    """
    with app.app_context():
        user = testutils.create_test_user('*****@*****.**')
        query = db.session.query(SessionActivity)
        assert query.count() == len(app.kvsession_store.keys())

        with app.test_client() as client:
            # After logging in, there should be one session in the kv-store and
            # one SessionActivity
            testutils.login_user_via_view(client, user=user)
            assert testutils.client_authenticated(client)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert query.count() == len(app.kvsession_store.keys())

            # Sessions are not deleted upon logout
            client.get(flask_security.url_for_security('logout'))
            assert len(app.kvsession_store.keys()) == 1
            query = db.session.query(SessionActivity)
            assert query.count() == len(app.kvsession_store.keys())

            # After logging out and back in, the number of sessions correspond
            # to the number of SessionActivity entries.
            testutils.login_user_via_view(client, user=user)
            query = db.session.query(SessionActivity)
            assert query.count() == len(app.kvsession_store.keys())
Exemple #22
0
def send_welcome_email(user_record, user):
    """Send this email when user is created from backend.

    :param user_record: User record.
    :param user: User account.
    """
    user_record = user_record.replace_refs()
    code = user_record['organisation'].get('code', '')
    plain_platform_name = 'SONAR'
    pname = platform_name(user_record['organisation'])
    if pname:
        plain_platform_name = pname

    token = generate_reset_password_token(user)
    reset_link = url_for_security(
        'reset_password',
        token=token,
        next=f'/{code}',
        _external=True
    )

    send_email(
        [user_record['email']],
        f'{_("Welcome to")} {plain_platform_name}',
        'users/email/welcome', {
            'user': user_record,
            'reset_link': reset_link,
            'platform_name': plain_platform_name
        }
    )
Exemple #23
0
def login_user_via_view(client,
                        email=None,
                        password=None,
                        user=None,
                        login_url=None):
    r"""Attempt to log the given user in via the 'login' view on the client.

    :param client: client to send the request from.
    :param email: email of user account to log in with.
    :param password: password of user account to log in with.
    :param user: If present, ``user.email`` and ``user.password_plaintext`` \
        take precedence over the `email` and `password` parameters.
    :type user: :class:`invenio_accounts.models.User` (with the addition of \
        a ``password_plaintext`` field)
    :param login_url: URL to post login details to. Defaults to the current \
        application's login URL.

    :returns: The response object from the POST to the login form.
    """
    if user is not None:
        email = user.email
        password = user.password_plaintext
    return client.post(login_url or url_for_security('login'),
                       data={
                           'email': email,
                           'password': password
                       },
                       environ_base={'REMOTE_ADDR': '127.0.0.1'})
Exemple #24
0
def test_deposit_empty(api, users, location):
    with api.test_request_context(), api.test_client() as client:
        client.post(
            url_for_security("login"),
            data={
                "email": users[0]["email"],
                "password": "******"
            },
        )

        response = client.post("/sword/service-document")
        assert response.status_code == HTTPStatus.CREATED
        match = re.match("^http://localhost/sword/deposit/([^/]+)$",
                         response.headers["Location"])
        assert match is not None
        pid_value = match.group(1)
        _, record = pid_resolver.resolve(pid_value)
        assert dict(record) == {
            "metadata": {},
            "$schema": "http://localhost/schemas/deposits/deposit-v1.0.0.json",
            "_deposit": {
                "id": pid_value,
                "status": "published",
                "owners": [users[0]["id"]],
                "created_by": users[0]["id"],
            },
            "_bucket": record.bucket_id,
        }

        # POSTing with no metadata, by-reference, or request body should result in no files being created.
        assert ObjectVersion.query.filter_by(bucket=record.bucket).count() == 0
def _create_new_record_version(app):
    """Create a new version of a record existing before the upgrade."""
    from invenio_accounts.models import User
    from flask_security import url_for_security
    from flask_security.utils import hash_password
    from flask import url_for
    from invenio_oauth2server.models import Token
    user = User.query.filter(User.email == '*****@*****.**').one()
    user.password = hash_password('123')
    token = Token.create_personal('other_token', user.id, scopes=[])
    headers = [('Authorization', 'Bearer {}'.format(token.access_token)),
               ('Content-type', 'application/json')]
    db.session.commit()
    with app.test_request_context():
        login_url = url_for_security('login')
    with app.test_client() as client:
        res = client.post(login_url,
                          data={
                              'email': '*****@*****.**',
                              'password': '******'
                          })
        assert res.status_code == 302
        url = url_for('b2share_records_rest.b2rec_list',
                      version_of='1033083fedf4408fb5611f23527a926d')
        res = client.post(url, headers=headers)
        assert res.status_code == 201
def test_put_metadata_document(api, users, location, es):
    with api.test_request_context(), api.test_client() as client:
        client.post(
            url_for_security("login"),
            data={
                "email": users[0]["email"],
                "password": "******"
            },
        )
        record = SWORDDeposit.create({})
        record.commit()
        db.session.commit()

        response = client.put(
            "/sword/deposit/{}/metadata".format(record.pid.pid_value),
            headers={
                "Metadata-Format":
                "http://purl.org/net/sword/3.0/types/Metadata",
                "Content-Type": "application/ld+json",
            },
            data=json.dumps({}),
        )
        assert response.status_code == HTTPStatus.NO_CONTENT

        record = SWORDDeposit.get_record(record.id)
        assert (record["swordMetadataSourceFormat"] ==
                "http://purl.org/net/sword/3.0/types/Metadata")
        assert any("http://purl.org/net/sword/3.0/terms/formattedMetadata" in
                   link["rel"] and link["metadataFormat"] ==
                   "http://purl.org/net/sword/3.0/types/Metadata"
                   for link in record.get_status_as_jsonld()["links"])
Exemple #27
0
def resend_invitation(user_id):
    """
    For the purpose of re-sending a lost "activation" email, this endpoint allows 
    an admin to re-send that message. 
    This is a convenience option in the admin's dashboard (on the individual user's profile) but it 
    is no different than the reset password flow. We simply generate a reset password token and send the 
    email using our "invite" custom template. 
    Something to note: You can instruct your users who might have misplaced their "activation" email to just 
    use the password reset link from the login page. It's the same flow and they can request a new password 
    with their email address. 
    """
    user = Users.query.get(user_id)
    try:
        link = url_for_security('reset_password',
                                token=generate_reset_password_token(user),
                                _external=True)
        subject = 'Activate your account for the Health Tracker'
        if Config.ORG:
            subject = f'Activate your account for the {Config.ORG} Health Tracker'
        send_mail(subject, user.email, 'invite_new_user', reset_link=link)
        flash('User invitation email was sent.', category='success')
    except Exception as e:
        app.logger.debug(e)
        db.session.rollback()
        flash('User invitation email was not sent, there was an error',
              category='error')
    return redirect(url_for('single_user', id=user_id))
def test_get_metadata_document(api, users, location, es):
    with api.test_request_context(), api.test_client() as client:
        client.post(
            url_for_security("login"),
            data={
                "email": users[0]["email"],
                "password": "******"
            },
        )

        record = SWORDDeposit.create({})
        record.set_metadata({"dc:title": "Deposit title"}, SWORDMetadata)
        record.commit()
        db.session.commit()

        response = client.get("/sword/deposit/{}".format(record.pid.pid_value))
        assert response.status_code == HTTPStatus.OK

        response = client.get("/sword/deposit/{}/metadata".format(
            record.pid.pid_value))
        assert response.status_code == HTTPStatus.OK
        assert response.is_json
        assert response.json == {
            "@id":
            "http://localhost/sword/deposit/{}".format(record.pid.pid_value),
            "@context": "https://swordapp.github.io/swordv3/swordv3.jsonld",
            "dc:title": "Deposit title",
        }
def test_webhook_post_no_token(app, tester_id, receiver):
    ds = app.extensions["security"].datastore

    with app.test_request_context():
        user = ds.get_user(tester_id)
        with app.test_client() as client:
            # Manual login via view
            response = client.post(
                url_for_security("login"),
                data={"email": user.email, "password": user.password},
                environ_base={"REMOTE_ADDR": "127.0.0.1"},
            )

            assert response.status_code == 302
            assert user.get_id() == current_user.get_id()

            payload = dict(somekey="somevalue")
            response = make_request(
                None,
                client.post,
                "invenio_webhooks.event_list",
                urlargs=dict(receiver_id="test-receiver"),
                data=payload,
                code=202,
            )

            make_request(
                None,
                client.get,
                "invenio_webhooks.event_item",
                urlargs=dict(receiver_id=response.headers["X-Hub-Event"], event_id=response.headers["X-Hub-Delivery"]),
                data=payload,
                code=202,
            )
Exemple #30
0
def test_file_get(fixtures_path, location, es, api, users):
    with api.test_request_context(), api.test_client() as client:
        client.post(
            url_for_security("login"),
            data={
                "email": users[0]["email"],
                "password": "******"
            },
        )

        bagit_record = create_bagit_record(fixtures_path)

        status_document = bagit_record.get_status_as_jsonld()
        assert len(status_document["links"]) > 0

        expected_content = []
        for file in bagit_record.files:
            with file.obj.file.storage().open() as f:
                expected_content.append(f.read())
        expected_content.sort()

        actual_content = []
        for link in status_document["links"]:
            response = client.get(link["@id"])
            assert response.status_code == HTTPStatus.OK
            actual_content.append(response.data)
        actual_content.sort()

        assert expected_content == actual_content
Exemple #31
0
def test_repeated_login_session_population(app):
    """Verify that the number of SessionActivity entries match the number of
    sessions in the kv-store, when logging in with one user."""
    InvenioAccounts(app)
    app.register_blueprint(blueprint)

    user = testutils.create_test_user()
    query = _datastore.db.session.query(SessionActivity)
    assert query.count() == len(testutils.get_kvsession_keys())

    with app.test_client() as client:
        # After logging in, there should be one session in the kv-store and
        # one SessionActivity
        testutils.login_user_via_view(client, user=user)
        assert testutils.client_authenticated(client)
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == 1
        assert query.count() == len(testutils.get_kvsession_keys())

        # Sessions are not deleted upon logout
        client.get(flask_security.url_for_security('logout'))
        assert len(testutils.get_kvsession_keys()) == 1
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == len(testutils.get_kvsession_keys())

        # After logging out and back in, the number of sessions correspond to
        # the number of SessionActivity entries.
        testutils.login_user_via_view(client, user=user)
        query = _datastore.db.session.query(SessionActivity)
        assert query.count() == len(testutils.get_kvsession_keys())
Exemple #32
0
def before_request():
    #flask sessions expire once you close the browser unless you have a permanent session
    session.permanent = True
    #By default in Flask, permanent_session_lifetime is set to 31 days.
    app.permanent_session_lifetime = timedelta(minutes=30)
    max_login_retry = 5

    ip = request.headers['X-Real-IP'] or request.headers['Remote_Addr']
    if (not getattr(g.identity, 'user',
                    None)) and request.path == url_for_security('login'):
        if request.method == 'POST' and request.form['password']:
            login_retry = session.get('login_retry', 0) + 1
            session['login_retry'] = login_retry
            #使用redis来限制ip登录限制
            key = session_ip_prefix + ip
            with redis.pipeline() as pipe:
                pipe.incr(key).expire(key, 2 * 3600).execute()
            #print(type(redis.get(key)))
            ip_retry_count = int(redis.get(key))

            if login_retry > max_login_retry or ip_retry_count > max_login_retry:
                return render_template('hintInfo.html', msg='登录次数超出限制,请2小时后重试')

    log.info(ip + " enter into " + request.path
             or '' + " for " + request.endpoint
             or '' + " of http method:" + request.method)
def test_repeated_login_session_population(app):
    """Verify session population on repeated login."""
    with app.app_context():
        user = testutils.create_test_user('*****@*****.**')
        query = db.session.query(SessionActivity)
        assert query.count() == len(app.kvsession_store.keys())

        with app.test_client() as client:
            # After logging in, there should be one session in the kv-store and
            # one SessionActivity
            testutils.login_user_via_view(client, user=user)
            assert testutils.client_authenticated(client)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            first_login_session_id = app.kvsession_store.keys()[0]

            # Sessions are not deleted upon logout
            client.get(flask_security.url_for_security('logout'))
            assert len(app.kvsession_store.keys()) == 1
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            # Session id doesn't change after logout
            assert first_login_session_id == app.kvsession_store.keys()[0]

            # After logging out and back in, the inital session id in the
            # sessionstore should be updated, and there should be two
            # SessionActivity entries (the old one and the regenerated).
            testutils.login_user_via_view(client, user=user)
            query = db.session.query(SessionActivity)
            assert query.count() == 2
            assert len(app.kvsession_store.keys()) == 1
            assert first_login_session_id != app.kvsession_store.keys()[0]
Exemple #34
0
def test_repeated_login_session_population(app):
    """Verify session population on repeated login."""
    with app.app_context():
        user = testutils.create_test_user('*****@*****.**')
        query = db.session.query(SessionActivity)
        assert query.count() == len(app.kvsession_store.keys())

        with app.test_client() as client:
            # After logging in, there should be one session in the kv-store and
            # one SessionActivity
            testutils.login_user_via_view(client, user=user)
            assert testutils.client_authenticated(client)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            first_login_session_id = app.kvsession_store.keys()[0]

            # SessionActivity is deleted upon logout
            client.get(flask_security.url_for_security('logout'))
            query = db.session.query(SessionActivity)
            assert query.count() == 0
            # Session id changes after logout
            assert len(app.kvsession_store.keys()) == 1
            assert first_login_session_id != app.kvsession_store.keys()[0]

            # After logging out and back in, the should be one
            # SessionActivity entry.
            testutils.login_user_via_view(client, user=user)
            query = db.session.query(SessionActivity)
            assert query.count() == 1
            assert len(app.kvsession_store.keys()) == 1
            assert first_login_session_id != app.kvsession_store.keys()[0]
def test_file_put(api, deposit, files, users):
    """PUT a deposit file."""
    with api.test_request_context():
        with api.test_client() as client:
            old_file_id = files[0].file_id
            old_filename = files[0].key
            new_filename = '{0}-new-name'.format(old_filename)
            # test rename file (without login)
            res = client.put(url_for('invenio_deposit_rest.depid_file',
                                     pid_value=deposit['_deposit']['id'],
                                     key=old_filename),
                             data=json.dumps({'filename': new_filename}))
            assert res.status_code == 401
            # login
            res = client.post(url_for_security('login'),
                              data=dict(email=users[0]['email'],
                                        password="******"))
            # test rename file
            res = client.put(url_for('invenio_deposit_rest.depid_file',
                                     pid_value=deposit['_deposit']['id'],
                                     key=old_filename),
                             data=json.dumps({'filename': new_filename}))
            deposit_id = deposit.id
            db.session.expunge(deposit.model)
            deposit = Deposit.get_record(deposit_id)
            files = list(deposit.files)
            assert res.status_code == 200
            assert new_filename == files[0].key
            assert old_file_id == files[0].file_id
            data = json.loads(res.data.decode('utf-8'))
            obj = files[0]
            assert data['filename'] == obj.key
            assert data['checksum'] == obj.file.checksum
            assert data['id'] == str(obj.file.id)
Exemple #36
0
def test_read_content(client, superuser, admin, moderator, submitter, user,
                      user_without_org, document_with_file):
    """Test read documents permissions."""

    file_name = 'test1.pdf'
    users = [
        superuser, admin, moderator, submitter, user, user_without_org, None
    ]
    url_file_content = url_for('invenio_records_files.doc_object_api',
                               pid_value=document_with_file.get('pid'),
                               key=file_name)
    open_access_code = "coar:c_abf2"
    document_with_file.files[file_name]['access'] = open_access_code
    document_with_file.commit()
    for u, status in zip(users, [200, 200, 200, 200, 200, 200, 200]):
        if u:
            login_user_via_session(client, email=u['email'])
        else:
            client.get(url_for_security('logout'))
        res = client.get(url_file_content)
        assert res.status_code == status
    # Masked document
    document_with_file['masked'] = 'masked_for_all'
    document_with_file.commit()
    for u, status in zip(users, [200, 200, 200, 404, 404, 404, 404]):
        if u:
            login_user_via_session(client, email=u['email'])
        else:
            client.get(url_for_security('logout'))
        res = client.get(url_file_content)
        assert res.status_code == status

    del document_with_file['masked']

    # restricted files
    restricted_code = "coar:c_16ec"
    document_with_file.files[file_name]['access'] = restricted_code
    document_with_file.files[file_name][
        'restricted_outside_organisation'] = True
    document_with_file.commit()
    for u, status in zip(users, [200, 200, 200, 200, 200, 404, 404]):
        if u:
            login_user_via_session(client, email=u['email'])
        else:
            client.get(url_for_security('logout'))
        res = client.get(url_file_content)
        assert res.status_code == status
def test_no_log_in_message_for_logged_in_users(app):
    """Test the password reset form for logged in users.

    Password reset form should not show log in or sign up messages for logged
    in users.
    """
    with app.app_context():
        forgot_password_url = url_for_security("forgot_password")

    with app.test_client() as client:
        log_in_message = _("Log in").encode("utf-8")
        sign_up_message = _("Sign up").encode("utf-8")

        resp = client.get(forgot_password_url)
        assert resp.status_code == 200
        assert log_in_message in resp.data
        assert sign_up_message in resp.data

        test_email = "*****@*****.**"
        test_password = "******"
        resp = client.post(
            url_for_security("register"),
            data=dict(
                email=test_email,
                password=test_password,
            ),
            environ_base={"REMOTE_ADDR": "127.0.0.1"},
        )

        resp = client.post(
            url_for_security("login"),
            data=dict(
                email=test_email,
                password=test_password,
            ),
        )

        resp = client.get(forgot_password_url, follow_redirects=True)
        if resp.status_code == 200:
            # This behavior will be phased out in future Flask-Security
            # release as per mattupstate/flask-security#291
            assert log_in_message not in resp.data
            assert sign_up_message not in resp.data
        else:
            # Future Flask-Security will redirect to post login view when
            # authenticated user requests password reset page.
            assert resp.data == client.get(app.config["SECURITY_POST_LOGIN_VIEW"]).data
def test_file_delete(api, deposit, files, users):
    """Test delete file."""
    with api.test_request_context():
        # the user is the owner
        with api.test_client() as client:
            deposit_id = deposit.id
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 401
            db.session.expunge(deposit.model)
            deposit = Deposit.get_record(deposit_id)
            assert files[0].key in deposit.files
            assert deposit.files[files[0].key] is not None
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # delete resource
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 204
            assert res.data == b''
            db.session.expunge(deposit.model)
            deposit = Deposit.get_record(deposit_id)
            assert files[0].key not in deposit.files

        # the user is NOT the owner
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[1]['email'],
                password="******"
            ))
            # delete resource
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 403
def test_file_delete(api, deposit, files, users):
    """Test delete file."""
    with api.test_request_context():
        # the user is the owner
        with api.test_client() as client:
            deposit_id = deposit.id
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 401
            db.session.expunge(deposit.model)
            deposit = Deposit.get_record(deposit_id)
            assert files[0].key in deposit.files
            assert deposit.files[files[0].key] is not None
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # delete resource
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 204
            assert res.data == b''
            db.session.expunge(deposit.model)
            deposit = Deposit.get_record(deposit_id)
            assert files[0].key not in deposit.files

        # the user is NOT the owner
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[1]['email'],
                password="******"
            ))
            # delete resource
            res = client.delete(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 403
def test_clean_session_table(task_app):
    """Test clean session table."""
    # set session lifetime
    task_app.permanent_session_lifetime = timedelta(seconds=20)

    # protected page
    @task_app.route('/test', methods=['GET'])
    @login_required
    def test():
        return 'test'

    with task_app.test_request_context():
        user1 = create_test_user(email='*****@*****.**')
        user2 = create_test_user(email='*****@*****.**')

        with task_app.test_client() as client:
            client.post(url_for_security('login'), data=dict(
                email=user1.email,
                password=user1.password_plaintext,
            ))
        assert len(SessionActivity.query.all()) == 1
        sleep(15)

        with task_app.test_client() as client:
            client.post(url_for_security('login'), data=dict(
                email=user2.email,
                password=user2.password_plaintext,
            ))
            assert len(SessionActivity.query.all()) == 2
            sleep(10)

            clean_session_table.s().apply()
            assert len(SessionActivity.query.all()) == 1

            protected_url = url_for('test')

            res = client.get(protected_url)
            assert res.status_code == 200

            sleep(15)
            clean_session_table.s().apply()
            assert len(SessionActivity.query.all()) == 0

            res = client.get(protected_url)
            # check if the user is really logout
            assert res.status_code == 302
def login_user_via_view(client, email, password, login_url=None):
    """Attempt to log the given user in via the 'login' view on the client.

    Returns the response object.
    """
    return client.post(login_url or url_for_security('login'),
                       data={'email': email, 'password': password},
                       environ_base={'REMOTE_ADDR': '127.0.0.1'})
def test_view(app):
    """Test view."""
    with app.app_context():
        login_url = url_for_security('login')

    with app.test_client() as client:
        res = client.get(login_url)
        assert res.status_code == 200
Exemple #43
0
 def _handle_view(self, name, **kwargs):
     if not self.is_accessible():
         if current_user.is_authenticated:
             # send 403 permission denied
             return self.inaccessible_callback(name, **kwargs)
         else:
             # redirect to login
             return redirect(url_for_security('login', next=request.path))
def test_file_get(api, deposit, files, users):
    """Test get file."""
    with api.test_request_context():
        # the user is the owner
        with api.test_client() as client:
            # get resource without login
            res = client.get(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 401
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # get resource
            res = client.get(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 200
            data = json.loads(res.data.decode('utf-8'))
            obj = files[0]
            assert data['filename'] == obj.key
            assert data['checksum'] == obj.file.checksum
            assert data['id'] == str(obj.file.id)

        # the user is NOT the owner
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[1]['email'],
                password="******"
            ))
            # get resource
            res = client.get(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key=files[0].key
            ))
            assert res.status_code == 403
def client_authenticated(client, test_url=None):
    """Attempt to get the change password page with the given client object.

    Returns True if the client can get the change password page without getting
    redirected and flask_login's `current_user` object isn't anonymous.
    """
    response = client.get(test_url or url_for_security('change_password'))

    return (response.status_code == 200 and
            not flask_login.current_user.is_anonymous)
def test_no_log_in_message_for_logged_in_users(app):
    """Test the password reset form for logged in users.

    Password reset form should not show log in or sign up messages for logged
    in users.
    """
    InvenioAccounts(app)
    app.register_blueprint(blueprint)
    with app.app_context():
        forgot_password_url = url_for_security('forgot_password')

    with app.test_client() as client:
        log_in_message = _('Log In').encode('utf-8')
        sign_up_message = _('Sign Up').encode('utf-8')

        resp = client.get(forgot_password_url)
        assert resp.status_code == 200
        assert log_in_message in resp.data
        assert sign_up_message in resp.data

        test_email = '*****@*****.**'
        test_password = '******'
        resp = client.post(url_for_security('register'), data=dict(
            email=test_email,
            password=test_password,
        ), environ_base={'REMOTE_ADDR': '127.0.0.1'})

        resp = client.post(url_for_security('login'), data=dict(
            email=test_email,
            password=test_password,
        ))

        resp = client.get(forgot_password_url, follow_redirects=True)
        if resp.status_code == 200:
            # This behavior will be phased out in future Flask-Security
            # release as per mattupstate/flask-security#291
            assert log_in_message not in resp.data
            assert sign_up_message not in resp.data
        else:
            # Future Flask-Security will redirect to post login view when
            # authenticated user requests password reset page.
            assert resp.data == client.get(
                app.config['SECURITY_POST_LOGIN_VIEW']).data
Exemple #47
0
    def _handle_view(self, name, **kwargs):
        next_url = '/admin'
        if self.url:
            next_url = self.url

        if not current_user.is_authenticated:
            return redirect(url_for_security('login', next=next_url))

        if not self.is_accessible():
            return self.inaccessible_callback(name, **kwargs)
def test_view(app):
    """Test view."""
    InvenioAccounts(app)
    app.register_blueprint(blueprint)

    with app.app_context():
        login_url = url_for_security("login")

    with app.test_client() as client:
        res = client.get(login_url)
        assert res.status_code == 200
Exemple #49
0
def login_user(app):
    """Login a user."""

    with app.test_request_context():
        login_url = url_for_security('login')

    def login(user_info, client):
        res = client.post(login_url, data={
            'email': user_info.email, 'password': user_info.password})
        assert res.status_code == 302
    return login
def test_files_get(api, deposit, files, users):
    """Test rest files get."""
    with api.test_request_context():
        # the user is the owner
        with api.test_client() as client:
            # get resources without login
            res = client.get(
                url_for('invenio_deposit_rest.depid_files',
                        pid_value=deposit['_deposit']['id']))
            assert res.status_code == 401
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # get resources
            res = client.get(
                url_for('invenio_deposit_rest.depid_files',
                        pid_value=deposit['_deposit']['id']),
                headers=[('Content-Type', 'application/json'),
                         ('Accept', 'application/json')]
            )
            assert res.status_code == 200
            data = json.loads(res.data.decode('utf-8'))
            assert data[0]['checksum'] == files[0].file.checksum
            assert data[0]['filename'] == files[0].key
            assert data[0]['filesize'] == files[0].file.size

        # the user is NOT the owner
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[1]['email'],
                password="******"
            ))
            # get resources
            res = client.get(
                url_for('invenio_deposit_rest.depid_files',
                        pid_value=deposit['_deposit']['id']))
            assert res.status_code == 403
Exemple #51
0
def openid_login(provider):
    """Return OAuth2 login view for the given provider.

    :param provider: OAuth2 provider.
    """

    # get parser for provider
    parser = eval(str.format('{0}_parser', provider.lower()))
    code = request.args.get('code')
    oauth_kwargs = current_app.config[str.format('OAUTH_{0}', provider.upper())]
    c = Client(**oauth_kwargs)
    # get request token
    c.request_token(parser=parser, redirect_uri=current_app.config['KINORSI_SERVER_HOST'], grant_type='authorization_code', code=code)

    if hasattr(c, 'error') and c.error != 0:
        current_app.logger.info(c.error_description)
        return redirect(url_for_security('login'))
    else:
        session[u'access_token'] = c.access_token
        session[u'refresh_token'] = c.refresh_token
        session[u'expires_in'] = c.expires_in
        # get open id
        res = c.request("/oauth2.0/me", parser=parser)
        res['oauth_consumer_key'] = res['client_id']
        # get nickname.
        user_info = c.request('/user/get_user_info?' + urllib.urlencode(res), method='GET', parser=parser)
        # 看看是不是已经在数据库中了,没有就写一个
        security = current_app.extensions['security']
        datastore = security.datastore
        user = datastore.find_user(openid=res['openid'], provider=provider.lower())
        if user is None:
            user = datastore.create_user(openid=res['openid'], provider=provider.lower(), nickname=user_info['nickname'], avatar=user_info['figureurl_qq_1'])
            datastore.commit()
        else:
            pass
            #print 'user :'******'is here'

        login_user(user)

        next_url = get_url(request.args.get('next')) or get_url(request.form.get('next')) \
            or current_app.extensions['security'].post_login_view or ''

        # 如果用户没有绑定,可以让用户尝试进行首次的帐号绑定。如果不绑也可以在以后再绑
        # 2014-12-5 先去掉绑定功能。不然似乎有点复杂过头了。
        if user.bind_username is None and user.bind_email is None and (user.bind_remind is None or user.bind_remind ):
            form_class = _security.login_form
            form = form_class()
            form.next.data = next_url

            return render_template('security/bind_user.html', bind_form=form)

        return redirect(next_url)
def client_authenticated(client, test_url=None):
    r"""Attempt to access the change password page with the given client.

    :param test_url: URL to attempt to get. Defaults to the current \
            application's "change password" page.
    :returns: True if the client can get the test_url without getting \
        redirected and ``flask_login.current_user`` is not anonymous \
        after requesting the page.
    """
    response = client.get(test_url or url_for_security('change_password'))

    return (response.status_code == 200 and
            not flask_login.current_user.is_anonymous)
def test_edit_deposit_users(app, db, es, users, location, deposit,
                            json_headers, user_info, status):
    """Test edit deposit by the owner."""
    deposit_id = deposit['_deposit']['id']
    with app.test_request_context():
        with app.test_client() as client:
            if user_info:
                # login
                res = client.post(url_for_security('login'), data=user_info)
            res = client.put(
                url_for('invenio_deposit_rest.dep_item', pid_value=deposit_id),
                data=json.dumps({"title": "bar"}),
                headers=json_headers
            )
            assert res.status_code == status
def test_files_get_without_files(api, deposit, users):
    """Test rest files get a deposit without files."""
    with api.test_request_context():
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # get resources
            res = client.get(
                url_for('invenio_deposit_rest.depid_files',
                        pid_value=deposit['_deposit']['id']))
            assert res.status_code == 200
            data = json.loads(res.data.decode('utf-8'))
            assert data == []
def test_file_put_not_found_file_not_exist(api, deposit, files, users):
    """Test put file and file doesn't exist."""
    with api.test_request_context():
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            res = client.put(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key='not_found'),
                data=json.dumps({'filename': 'foobar'})
            )
            assert res.status_code == 404
def test_file_get_not_found(api, deposit, users):
    """Test get file."""
    with api.test_request_context():
        with api.test_client() as client:
            # login
            res = client.post(url_for_security('login'), data=dict(
                email=users[0]['email'],
                password="******"
            ))
            # get resource
            res = client.get(url_for(
                'invenio_deposit_rest.depid_file',
                pid_value=deposit['_deposit']['id'],
                key='not_found'
            ))
            assert res.status_code == 404
def test_login_remember_me_disabled(app, users):
    """Test login remember me is disabled."""
    email = users[0]['email']
    password = users[0]['password']
    _security.login_form = LoginForm
    with app.test_client() as client:
        res = client.post(
            url_for_security('login'),
            data={'email': email, 'password': password, 'remember': True},
            environ_base={'REMOTE_ADDR': '127.0.0.1'})
        # check the remember_me cookie is not there
        name = '{0}='.format(COOKIE_NAME)
        assert all([
            name not in val for val in res.headers.values()])
        # check the session cookie is still there
        assert any([
            'session=' in val for val in res.headers.values()])
def test_headers_info(app, users):
    """Test if session and user id is set response header."""
    u = users[0]
    url = url_for_security('change_password')
    with app.app_context():
        with app.test_client() as client:
            response = client.get(url)
            # Not logged in, so only session id available
            assert not testutils.client_authenticated(client)
            assert 'X-Session-ID' in response.headers
            assert 'X-User-ID' not in response.headers
            # Login
            testutils.login_user_via_session(client, email=u['email'])
            response = client.get(url)
            cookie = requests.utils.dict_from_cookiejar(client.cookie_jar)
            assert response.headers['X-Session-ID'] == \
                cookie['session'].split('.')[0]
            assert int(response.headers['X-User-ID']) == u['id']
def test_forgot_password_token(app, users, sleep, expired):
    """Test expiration of token for password reset."""
    token = generate_reset_password_token(users[0]['obj'])
    reset_link = url_for_security('reset_password', token=token)

    with app.test_client() as client:
        res = client.get(reset_link, follow_redirects=True)
        time.sleep(sleep)
        if expired:
            app.config['SECURITY_MSG_PASSWORD_RESET_EXPIRED'][0] % {
                'within': app.config['SECURITY_RESET_PASSWORD_WITHIN'],
                'email': users[0]['email']
            } in res.get_data(as_text=True)
        else:
            assert (
                '<button type="submit" class="btn btn-primary btn-lg '
                'btn-block">Reset Password</button>'
            ) in res.get_data(as_text=True)
def test_publish_merge_conflict(app, db, es, users, location, deposit,
                                json_headers, fake_schemas):
    """Test publish with merge conflicts."""
    with app.test_request_context():
        with app.test_client() as client:
            user_info = dict(email=users[0].email, password='******')
            # login
            res = client.post(url_for_security('login'), data=user_info)

            # create a deposit
            deposit = Deposit.create({"metadata": {
                "title": "title-1",
            }})
            deposit.commit()
            db.session.commit()
            # publish
            deposit.publish()
            db.session.commit()
            # edit
            deposit = deposit.edit()
            db.session.commit()
            # simulate a externally modification
            rid, record = deposit.fetch_published()
            rev_id = record.revision_id
            record.update({'metadata': {
                "title": "title-2.1",
            }})
            record.commit()
            db.session.commit()
            assert rev_id != record.revision_id
            # edit again and check the merging
            deposit.update({"metadata": {
                "title": "title-2.2",
            }})
            deposit.commit()

            current_search.flush_and_refresh('_all')

            deposit_id = deposit.pid.pid_value
            res = client.post(
                url_for('invenio_deposit_rest.depid_actions',
                        pid_value=deposit_id, action='publish'),
            )
            assert res.status_code == 409