Ejemplo n.º 1
0
def test_init():
    """Test extension initialization."""
    app = Flask('testapp')
    ext = InvenioREST(app)
    assert 'invenio-rest' in app.extensions

    app = Flask('testapp')
    ext = InvenioREST()
    assert 'invenio-rest' not in app.extensions
    ext.init_app(app)
    assert 'invenio-rest' in app.extensions
Ejemplo n.º 2
0
def test_match_serializers_query_arg(app):
    """Test match serializers query argument."""
    v = ContentNegotiatedMethodView(
        method_serializers=dict(
            GET={
                'application/json': 'json-get',
                'application/marcxml+xml': 'xml-get'}
        ),
        serializers_query_aliases={
            'json': 'application/json',
            'marcxml': 'application/marcxml+xml',
        },
        default_media_type='application/marcxml+xml',
        default_method_media_type=dict(
            GET='application/marcxml+xml',
        )
    )

    # enable serialization by query arg
    app.config['REST_MIMETYPE_QUERY_ARG_NAME'] = 'format'
    InvenioREST(app)

    arg_name = app.config['REST_MIMETYPE_QUERY_ARG_NAME']
    tests = [
        # Should serialize to marcxml
        (urlencode({arg_name: 'marcxml'}), 'application/json', 'xml-get'),
        # Should serialize to json
        (urlencode({arg_name: 'json'}), 'application/marcxml+xml',
         'json-get'),
        # Should serialize to json
        (urlencode({}), 'application/json', 'json-get'),
        # Should serialize to default (marcxml)
        (urlencode({'wrong_name': 'marcxml'}), None, 'xml-get'),
    ]

    for arg, accept, expected_serializer in tests:
        params = dict(headers=[('Accept', accept)],
                      query_string=arg) if accept else {}
        _test_march_serializers(app, v, params, 'GET', accept,
                                expected_serializer)

    # disable query arg, should serialize by headers even if query arg passed
    app.config['REST_MIMETYPE_QUERY_ARG_NAME'] = None
    InvenioREST(app)

    accept = 'application/json'
    params = dict(headers=[('Accept', accept)], query_string='format=marcxml')
    _test_march_serializers(app, v, params, 'GET', accept, 'json-get')
Ejemplo n.º 3
0
def test_error_handlers(app):
    """Error handlers view."""
    InvenioREST(app)

    @app.route("/<int:status_code>",
               methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD',
                        'TRACE', 'OPTIONS'])
    def test_view(status_code):
        abort(status_code)

    error_codes = [
        400, 401, 403, 404, 405, 406, 409, 410, 412, 422, 415, 429, 500, 501,
        502, 503, 504]

    with app.test_client() as client:
        verbs = [client.get, client.post, client.put, client.delete,
                 client.patch, client.trace, client.options, client.get]
        for s in error_codes:
            for verb in verbs:
                res = verb("/{0}".format(s))
                assert res.status_code == s
                if pkg_resources.get_distribution("werkzeug").\
                        version == '0.14.1' and s == 412:
                    # skip test because of the following issue:
                    # https://github.com/pallets/werkzeug/issues/1231
                    continue
                if verb != client.head:
                    data = json.loads(res.get_data(as_text=True))
                    assert data['status'] == s
                    assert data['message']
Ejemplo n.º 4
0
def app(request):
    """Flask application fixture."""
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)
    app.config.update(
        TESTING=True,
        SERVER_NAME='localhost:5000',
        SQLALCHEMY_DATABASE_URI=os.environ.get(
            'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'
        )
    )
    FlaskCLI(app)
    InvenioDB(app)
    InvenioREST(app)
    InvenioRecords(app)
    InvenioPIDStore(app)
    InvenioRecordsREST(app)

    with app.app_context():
        if not database_exists(str(db.engine.url)) and \
           app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
            create_database(db.engine.url)
        db.drop_all()
        db.create_all()

    def finalize():
        with app.app_context():
            db.drop_all()
            if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
                drop_database(db.engine.url)
            shutil.rmtree(instance_path)

    request.addfinalizer(finalize)
    return app
Ejemplo n.º 5
0
def test_error_handlers(app):
    """Error handlers view."""
    InvenioREST(app)

    @app.route("/<int:status_code>",
               methods=[
                   'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'TRACE',
                   'OPTIONS'
               ])
    def test_view(status_code):
        abort(status_code)

    error_codes = [
        400, 401, 403, 404, 405, 406, 409, 410, 412, 415, 429, 500, 501, 502,
        503, 504
    ]

    with app.test_client() as client:
        verbs = [
            client.get, client.post, client.put, client.delete, client.patch,
            client.trace, client.options, client.get
        ]
        for s in error_codes:
            for verb in verbs:
                res = verb("/{0}".format(s))
                assert res.status_code == s
                if verb != client.head:
                    data = json.loads(res.get_data(as_text=True))
                    assert data['status'] == s
                    assert data['message']
Ejemplo n.º 6
0
def app_with_flexible_registration(request):
    """Flask application fixture with Invenio Accounts."""
    from webargs import fields

    from invenio_accounts.views.rest import RegisterView, use_kwargs

    class MyRegisterView(RegisterView):

        post_args = {
            **RegisterView.post_args,
            'active': fields.Boolean(required=True)
        }

        @use_kwargs(post_args)
        def post(self, **kwargs):
            """Register a user."""
            return super(MyRegisterView, self).post(**kwargs)

    api_app = _app_factory()
    InvenioREST(api_app)
    InvenioAccountsREST(api_app)

    api_app.config['ACCOUNTS_REST_AUTH_VIEWS']['register'] = MyRegisterView

    api_app.register_blueprint(create_blueprint(api_app))

    _database_setup(api_app, request)
    yield api_app
Ejemplo n.º 7
0
def app(request):
    """Flask application fixture."""
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)
    app.config.update(
        TESTING=True,
        SERVER_NAME='localhost:5000',
        SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI',
                                               'sqlite:///test.db'),
        SQLALCHEMY_TRACK_MODIFICATIONS=True,
        RECORDS_REST_ENDPOINTS=config.RECORDS_REST_ENDPOINTS,
        # No permission checking
        RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_SEARCH_INDEX=ES_INDEX,
        RECORDS_REST_SORT_OPTIONS={
            ES_INDEX: dict(year=dict(fields=['year'], ))
        },
    )
    app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = TestSearch

    # update the application with the configuration provided by the test
    if hasattr(request, 'param') and 'config' in request.param:
        app.config.update(**request.param['config'])

    FlaskCLI(app)
    InvenioDB(app)
    InvenioREST(app)
    InvenioRecords(app)
    InvenioPIDStore(app)
    InvenioSearch(app)
    InvenioAccess(app)
    InvenioRecordsREST(app)

    with app.app_context():
        # Setup app
        if not database_exists(str(db.engine.url)) and \
           app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
            create_database(db.engine.url)
        db.drop_all()
        db.create_all()
        if current_search_client.indices.exists(ES_INDEX):
            current_search_client.indices.delete(ES_INDEX)
            current_search_client.indices.create(ES_INDEX)
        prepare_indexing(app)

    with app.app_context():
        # Yield app in request context
        with app.test_request_context():
            yield app

    with app.app_context():
        # Teardown app
        db.drop_all()
        if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
            drop_database(db.engine.url)
        shutil.rmtree(instance_path)
Ejemplo n.º 8
0
def app(request):
    """Flask application fixture."""
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)
    es_index = 'invenio_records_rest_test_index'
    app.config.update(
        TESTING=True,
        SERVER_NAME='localhost:5000',
        SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI',
                                               'sqlite:///test.db'),
        SQLALCHEMY_TRACK_MODIFICATIONS=True,
        RECORDS_REST_ENDPOINTS=config.RECORDS_REST_ENDPOINTS,
        # No permission checking
        RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_SEARCH_INDEX=es_index,
        RECORDS_REST_SORT_OPTIONS={
            es_index: dict(year=dict(fields=['year'], ))
        },
        SEARCH_QUERY_ENHANCERS=[filter_record_access_query_enhancer],
    )
    app.config['RECORDS_REST_ENDPOINTS']['recid']['search_index'] = es_index

    # update the application with the configuration provided by the test
    if hasattr(request, 'param') and 'config' in request.param:
        app.config.update(**request.param['config'])

    FlaskCLI(app)
    InvenioDB(app)
    InvenioREST(app)
    InvenioRecords(app)
    InvenioPIDStore(app)
    InvenioSearch(app)
    InvenioAccess(app)
    InvenioRecordsREST(app)

    with app.app_context():
        if not database_exists(str(db.engine.url)) and \
           app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
            create_database(db.engine.url)
        db.drop_all()
        db.create_all()
        if current_search_client.indices.exists(es_index):
            current_search_client.indices.delete(es_index)
            current_search_client.indices.create(es_index)
        prepare_indexing(app)

    def finalize():
        with app.app_context():
            db.drop_all()
            if app.config['SQLALCHEMY_DATABASE_URI'] != 'sqlite://':
                drop_database(db.engine.url)
            shutil.rmtree(instance_path)

    request.addfinalizer(finalize)
    return app
Ejemplo n.º 9
0
def app(base_app):
    """Flask application fixture."""
    base_app._internal_jsonschemas = InvenioJSONSchemas(base_app)
    InvenioREST(base_app)
    InvenioRecordsREST(base_app)
    InvenioRecords(base_app)
    InvenioPIDStore(base_app)
    base_app.url_map.converters['pid'] = PIDConverter
    base_app.register_blueprint(create_blueprint_from_app(base_app))

    app_loaded.send(None, app=base_app)

    with base_app.app_context():
        yield base_app
Ejemplo n.º 10
0
def test_cors(app):
    """Test CORS support."""
    app.config['REST_ENABLE_CORS'] = True
    InvenioREST(app)

    @app.route('/')
    def cors_test():
        return 'test'

    with app.test_client() as client:
        res = client.get('/')
        assert not res.headers.get('Access-Control-Allow-Origin', False)
        res = client.get('/', headers=[('Origin', 'http://example.com')])
        assert res.headers['Access-Control-Allow-Origin'] == '*'
Ejemplo n.º 11
0
def app(base_app):
    """Flask full application fixture."""
    Breadcrumbs(base_app)
    InvenioDB(base_app)
    InvenioAccess(base_app)
    InvenioAccounts(base_app)
    InvenioFilesREST(base_app)
    InvenioOAuth2Server(base_app)
    InvenioOAuth2ServerREST(base_app)
    InvenioREST(base_app)
    InvenioSIPStore(base_app)
    base_app.register_blueprint(server_blueprint)
    base_app.register_blueprint(blueprint)
    with base_app.app_context():
        yield base_app
Ejemplo n.º 12
0
def app(base_app):
    """Flask application fixture."""
    Babel(base_app)
    InvenioAccounts(base_app)
    InvenioAccess(base_app)
    InvenioDB(base_app)
    InvenioFilesREST(base_app)
    InvenioRecords(base_app)
    InvenioRecordsUI(base_app)
    InvenioREST(base_app)
    InvenioIIIFAPI(base_app)
    InvenioIIIFManifest(base_app)

    with base_app.app_context():
        yield base_app
Ejemplo n.º 13
0
def test_init():
    """Test extension initialization."""
    app = Flask('testapp')
    ext = InvenioREST(app)
    assert 'invenio-rest' in app.extensions

    app = Flask('testapp')
    ext = InvenioREST()
    assert 'invenio-rest' not in app.extensions
    ext.init_app(app)
    assert 'invenio-rest' in app.extensions
Ejemplo n.º 14
0
def api(request):
    """Flask application fixture."""
    api_app = _app_factory(
        dict(
            SQLALCHEMY_DATABASE_URI=os.environ.get(
                'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'),
            SERVER_NAME='localhost',
            TESTING=True,
        ))

    InvenioREST(api_app)
    InvenioAccountsREST(api_app)
    api_app.register_blueprint(create_blueprint(api_app))

    _database_setup(api_app, request)

    yield api_app
Ejemplo n.º 15
0
def test_custom_httpexception(app):
    """Test custom HTTPException."""
    InvenioREST(app)

    class CustomBadRequest(HTTPException):
        code = 400
        description = 'test'

    @app.route('/')
    def test_view():
        raise CustomBadRequest()

    with app.test_client() as client:
        res = client.get('/')
        assert res.status_code == 400
        data = json.loads(res.get_data(as_text=True))
        assert data['message'] == 'test'
        assert data['status'] == 400
Ejemplo n.º 16
0
def app(request):
    """Basic Flask application."""
    instance_path = tempfile.mkdtemp()
    app = Flask("testapp")
    app.config.update(
        SQLALCHEMY_DATABASE_URI=os.getenv("SQLALCHEMY_DATABASE_URI",
                                          "sqlite://"),
        SQLALCHEMY_TRACK_MODIFICATIONS=False,
        TESTING=True,
        SECRET_KEY="testing",
        # SERVER_NAME='localhost:5000',
    )

    app.url_map.converters['pid'] = PIDConverter

    InvenioDB(app)
    InvenioPIDStore(app)
    InvenioRecords(app)
    InvenioAccounts(app)
    InvenioAccess(app)
    InvenioIndexer(app)
    InvenioSearch(app)
    InvenioREST(app)
    InvenioRecordsREST(app)
    InvenioConfigDefault(app)

    with app.app_context():
        db_url = str(db.engine.url)
        if db_url != "sqlite://" and not database_exists(db_url):
            create_database(db_url)
        db.create_all()

    def teardown():
        with app.app_context():
            db_url = str(db.engine.url)
            db.session.close()
            if db_url != "sqlite://":
                drop_database(db_url)
            shutil.rmtree(instance_path)

    request.addfinalizer(teardown)
    app.test_request_context().push()

    return app
Ejemplo n.º 17
0
def test_cors(app):
    """Test CORS support."""
    app.config['REST_ENABLE_CORS'] = True
    app.config['CORS_ALWAYS_SEND'] = False

    InvenioREST(app)

    @app.route('/')
    def cors_test():
        return 'test'

    with app.test_client() as client:
        res = client.get('/')
        assert not res.headers.get('Access-Control-Allow-Origin', False)
        assert not res.headers.get('Access-Control-Expose-Headers', False)
        res = client.get('/', headers=[('Origin', 'http://example.com')])
        assert res.headers['Access-Control-Allow-Origin'] == '*'
        assert len(res.headers['Access-Control-Expose-Headers'].split(',')) \
            == len(app.config['CORS_EXPOSE_HEADERS'])
Ejemplo n.º 18
0
def app(base_app):
    """Flask application fixture."""

    base_app._internal_jsonschemas = InvenioJSONSchemas(base_app)

    InvenioREST(base_app)
    InvenioRecordsREST(base_app)

    InvenioRecords(base_app)
    InvenioPIDStore(base_app)
    base_app.url_map.converters['pid'] = PIDConverter
    SampleExt(base_app)
    OARepoMappingIncludesExt(base_app)
    LoginManager(base_app)
    Permission(base_app)
    InvenioAccess(base_app)
    Principal(base_app)
    OARepoValidate(base_app)
    Actions(base_app)
    base_app.register_blueprint(
        invenio_records_rest.views.create_blueprint_from_app(base_app))
    login_manager = LoginManager()
    login_manager.init_app(base_app)
    login_manager.login_view = 'login'

    @login_manager.user_loader
    def basic_user_loader(user_id):
        user_obj = User.query.get(int(user_id))
        return user_obj

    @base_app.route('/test/login/<int:id>', methods=['GET', 'POST'])
    def test_login(id):
        print("test: logging user with id", id)
        response = make_response()
        user = User.query.get(id)
        login_user(user)
        set_identity(user)
        return response

    app_loaded.send(None, app=base_app)

    with base_app.app_context():
        yield base_app
Ejemplo n.º 19
0
def test_require_content_types(app):
    """Error handlers view."""
    InvenioREST(app)

    @app.route("/", methods=['POST'])
    @require_content_types('application/json', 'text/plain')
    def test_view():
        return "OK"

    with app.test_client() as client:
        res = client.post("/", content_type='application/json', data="{}")
        assert res.status_code == 200
        res = client.post("/", content_type='text/plain', data="test")
        assert res.status_code == 200
        res = client.post("/", content_type='application/xml', data="<d></d>")
        assert res.status_code == 415
        data = json.loads(res.get_data(as_text=True))
        assert data['status'] == 415
        assert 'application/json' in data['message']
        assert 'text/plain' in data['message']
Ejemplo n.º 20
0
def test_errors(app):
    """Error handlers view."""
    InvenioREST(app)

    @app.route('/', methods=['GET'])
    def test_rest():
        raise RESTException(description='error description')

    @app.route('/contenttype', methods=['GET'])
    def test_content_type():
        raise InvalidContentType(allowed_content_types=['application/json'])

    @app.route('/validationerror', methods=['GET'])
    def test_validation_error():
        raise RESTValidationError(
            errors=[FieldError('myfield', 'mymessage', code=10)])

    with app.test_client() as client:
        res = client.get('/')
        assert res.status_code == 200
        data = json.loads(res.get_data(as_text=True))
        assert data['status'] is None
        assert data['message'] == 'error description'

        res = client.get('/contenttype')
        assert res.status_code == 415
        data = json.loads(res.get_data(as_text=True))
        assert data['status'] == 415
        assert 'application/json' in data['message']

        res = client.get('/validationerror')
        assert res.status_code == 400
        data = json.loads(res.get_data(as_text=True))
        print(data)
        assert data['status'] == 400
        assert data['message'] == 'Validation error.'
        assert data['errors'] == [
            dict(field='myfield', message='mymessage', code=10)
        ]
Ejemplo n.º 21
0
def app():
    """Flask applicat-ion fixture."""
    instance_path = os.path.join(sys.prefix, 'var', 'test-instance')

    # empty the instance path
    if os.path.exists(instance_path):
        shutil.rmtree(instance_path)
    os.makedirs(instance_path)

    os.environ['INVENIO_INSTANCE_PATH'] = instance_path

    app_ = Flask('invenio-records-draft-testapp', instance_path=instance_path)
    app_.config.update(
        TESTING=True,
        JSON_AS_ASCII=True,
        SERVER_NAME='localhost:5000',
        SQLALCHEMY_TRACK_MODIFICATIONS=False,
        SQLALCHEMY_DATABASE_URI=os.environ.get(
            'SQLALCHEMY_DATABASE_URI',
            'sqlite:///:memory:'),
        SECURITY_PASSWORD_SALT='TEST_SECURITY_PASSWORD_SALT',
        SECRET_KEY='TEST_SECRET_KEY',
        INVENIO_INSTANCE_PATH=instance_path,
        RECORDS_REST_ENDPOINTS={},
    )

    InvenioDB(app_)
    InvenioREST(app_)
    InvenioIIIFAPI(app_)
    OARepoIIIFExt(app_)

    app_.register_blueprint(invenio_iiif.previewer.blueprint, url_prefix='/api/iiif/')

    app_loaded.send(None, app=app_)

    with app_.app_context():
        yield app_
Ejemplo n.º 22
0
def test_ratelimt(app):
    """Test CORS support."""
    app.config['RATELIMIT_GLOBAL'] = '1/day'
    app.config['RATELIMIT_STORAGE_URL'] = 'memory://'
    ext = InvenioREST(app)

    for handler in app.logger.handlers:
        ext.limiter.logger.addHandler(handler)

    @app.route('/a')
    def view_a():
        return 'a'

    @app.route('/b')
    def view_b():
        return 'b'

    with app.test_client() as client:
        res = client.get('/a')
        assert res.status_code == 200
        assert res.headers['X-RateLimit-Limit'] == '1'
        assert res.headers['X-RateLimit-Remaining'] == '0'
        assert res.headers['X-RateLimit-Reset']

        res = client.get('/a')
        assert res.status_code == 429
        assert res.headers['X-RateLimit-Limit']
        assert res.headers['X-RateLimit-Remaining']
        assert res.headers['X-RateLimit-Reset']

        # Global limit is per view.
        res = client.get('/b')
        assert res.status_code == 200
        assert res.headers['X-RateLimit-Limit']
        assert res.headers['X-RateLimit-Remaining']
        assert res.headers['X-RateLimit-Reset']
Ejemplo n.º 23
0
def test_errors(app):
    """Error handlers view."""
    InvenioREST(app)

    @app.route('/', methods=['GET'])
    def test_rest():
        raise RESTException(description='error description')

    @app.route('/contenttype', methods=['GET'])
    def test_content_type():
        raise InvalidContentType(allowed_contet_types=['application/json'])

    with app.test_client() as client:
        res = client.get('/')
        assert res.status_code == 200
        data = json.loads(res.get_data(as_text=True))
        assert data['status'] is None
        assert data['message'] == 'error description'

        res = client.get('/contenttype')
        assert res.status_code == 415
        data = json.loads(res.get_data(as_text=True))
        assert data['status'] == 415
        assert 'application/json' in data['message']
Ejemplo n.º 24
0
def app(request, search_class):
    """Flask application fixture.
    
    Note that RECORDS_REST_ENDPOINTS is used during application creation to
    create blueprints on the fly, hence once you have this fixture in a test,
    it's too late to customize the configuration variable. You can however
    customize it using parameterized tests:
    .. code-block:: python
    @pytest.mark.parametrize('app', [dict(
        endpoint=dict(
            search_class='conftest:TestSearch',
        )
    def test_mytest(app, db, es):
        # ...
    This will parameterize the default 'recid' endpoint in
    RECORDS_REST_ENDPOINTS.
    Alternatively:
    .. code-block:: python
    @pytest.mark.parametrize('app', [dict(
        records_rest_endpoints=dict(
            recid=dict(
                search_class='conftest:TestSearch',
            )
        )
    def test_mytest(app, db, es):
        # ...
    This will fully parameterize RECORDS_REST_ENDPOINTS.
    """
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)
    from records import config
    app.config.update(
        ACCOUNTS_JWT_ENABLE=False,
        INDEXER_DEFAULT_DOC_TYPE='record-v1.0.0',
        INDEXER_DEFAULT_INDEX=search_class.Meta.index,
        RECORDS_REST_ENDPOINTS=copy.deepcopy(config.RECORDS_REST_ENDPOINTS),
        RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_SEARCH_INDEX=search_class.Meta.index,
        SERVER_NAME='localhost:5000',
        CELERY_ALWAYS_EAGER=True,
        CELERY_RESULT_BACKEND='cache',
        CELERY_CACHE_BACKEND='memory',
        CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
        SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI',
                                               'sqlite:///test.db'),
        SQLALCHEMY_TRACK_MODIFICATIONS=True,
        TESTING=True,
    )
    app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = \
        search_class

    app.config['RECORDS_REST_ENDPOINTS']['recid']['create_permission_factory_imp'] = \
        user_id_1_perm

    app.config['RECORDS_REST_ENDPOINTS']['recid']['record_class'] = \
        SchemaEnforcingRecord

    app.secret_key = 'changeme'

    # Parameterize application.
    if hasattr(request, 'param'):
        if 'endpoint' in request.param:
            app.config['RECORDS_REST_ENDPOINTS']['recid'].update(
                request.param['endpoint'])
        if 'records_rest_endpoints' in request.param:
            original_endpoint = app.config['RECORDS_REST_ENDPOINTS']['recid']
            del app.config['RECORDS_REST_ENDPOINTS']['recid']
            for new_endpoint_prefix, new_endpoint_value in \
                request.param['records_rest_endpoints'].items():
                new_endpoint = dict(original_endpoint)
                new_endpoint.update(new_endpoint_value)
                app.config['RECORDS_REST_ENDPOINTS'][new_endpoint_prefix] = \
                    new_endpoint

    app.url_map.converters['pid'] = PIDConverter

    InvenioDB(app)
    InvenioREST(app)
    InvenioRecords(app)
    schemas = InvenioJSONSchemas(app)
    indexer = InvenioIndexer(app)
    InvenioPIDStore(app)
    search = InvenioSearch(app)
    search.register_mappings(search_class.Meta.index, 'records.mappings')
    schemas._state.register_schemas_dir(
        os.path.join(os.path.dirname(__file__), 'records', 'jsonschemas'))
    InvenioRecordsREST(app)
    InvenioAccess(app)
    explicit_acls = InvenioExplicitAcls(app)
    principal = Principal(app)

    login_manager = LoginManager()
    login_manager.init_app(app)
    login_manager.login_view = 'login'

    @login_manager.user_loader
    def basic_user_loader(user_id):
        user_obj = User.query.get(int(user_id))
        return user_obj

    app.register_blueprint(create_blueprint_from_app(app))

    @app.route('/test/login/<int:id>', methods=['GET', 'POST'])
    def test_login(id):
        print("test: logging user with id", id)
        response = make_response()
        user = User.query.get(id)
        login_user(user)
        set_identity(user)
        return response

    with app.app_context():
        yield app

    # Teardown instance path.
    shutil.rmtree(instance_path)
Ejemplo n.º 25
0
def base_app(request, test_metadata_format):
    """Flask application fixture."""
    instance_path = tempfile.mkdtemp()

    def init_app(app_):
        app_.config.update(
            CELERY_ALWAYS_EAGER=False,
            CELERY_CACHE_BACKEND="memory",
            CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
            CELERY_RESULT_BACKEND="cache",
            JSONSCHEMAS_URL_SCHEME="http",
            SECRET_KEY="CHANGE_ME",
            SECURITY_PASSWORD_SALT="CHANGE_ME_ALSO",
            SQLALCHEMY_DATABASE_URI=os.environ.get("SQLALCHEMY_DATABASE_URI",
                                                   "sqlite:///test.db"),
            SQLALCHEMY_TRACK_MODIFICATIONS=True,
            SQLALCHEMY_ECHO=False,
            TESTING=True,
            WTF_CSRF_ENABLED=False,
            DEPOSIT_SEARCH_API="/api/search",
            SECURITY_PASSWORD_HASH="plaintext",
            SECURITY_PASSWORD_SCHEMES=["plaintext"],
            SECURITY_DEPRECATED_PASSWORD_SCHEMES=[],
            THEME_SITENAME="Test Site",
            OAUTHLIB_INSECURE_TRANSPORT=True,
            OAUTH2_CACHE_TYPE="simple",
            ACCOUNTS_JWT_ENABLE=False,
            # This allows access to files across all of invenio-files-rest
            FILES_REST_PERMISSION_FACTORY=lambda *a, **kw: type(
                "Allow", (object, ), {"can": lambda self: True})(),
            FILES_REST_MULTIPART_CHUNKSIZE_MIN=10,
        )
        Babel(app_)
        FlaskCeleryExt(app_)
        Breadcrumbs(app_)
        OAuth2Provider(app_)
        InvenioDB(app_)
        InvenioAccounts(app_)
        InvenioAccess(app_)
        InvenioIndexer(app_)
        InvenioJSONSchemas(app_)
        InvenioOAuth2Server(app_)
        InvenioPIDStore(app_)
        InvenioRecords(app_)
        search = InvenioSearch(app_)
        search.register_mappings("deposits", "invenio_deposit.mappings")

    api_app = Flask("testapiapp", instance_path=instance_path)
    api_app.url_map.converters["pid"] = PIDConverter
    # initialize InvenioDeposit first in order to detect any invalid dependency
    InvenioDepositREST(api_app)

    init_app(api_app)
    InvenioREST(api_app)
    InvenioOAuth2ServerREST(api_app)
    InvenioRecordsREST(api_app)
    InvenioFilesREST(api_app)
    InvenioSword(api_app)
    api_app.register_blueprint(files_rest_blueprint)
    # api_app.register_blueprint(records_files_bp(api_app))
    api_app.register_blueprint(records_rest_bp(api_app))
    api_app.register_blueprint(invenio_files_rest_blueprint)

    # Register a test (alternate) metadata format
    api_app.config["SWORD_ENDPOINTS"]["depid"]["metadata_formats"][
        test_metadata_format] = TestMetadata

    app = Flask("testapp", instance_path=instance_path)
    app.url_map.converters["pid"] = PIDConverter
    # initialize InvenioDeposit first in order to detect any invalid dependency
    InvenioDeposit(app)
    init_app(app)
    app.register_blueprint(accounts_blueprint)
    app.register_blueprint(oauth2server_settings_blueprint)
    InvenioAssets(app)
    InvenioSearchUI(app)
    InvenioRecordsUI(app)
    app.register_blueprint(records_ui_bp(app))
    app.wsgi_app = DispatcherMiddleware(app.wsgi_app,
                                        {"/api": api_app.wsgi_app})

    with app.app_context():
        if str(db.engine.url) != "sqlite://" and not database_exists(
                str(db.engine.url)):
            create_database(str(db.engine.url))
        db.create_all()

    yield app

    with app.app_context():
        if str(db.engine.url) != "sqlite://":
            drop_database(str(db.engine.url))
        shutil.rmtree(instance_path)
Ejemplo n.º 26
0
def base_app(request):
    """Flask application fixture."""
    instance_path = tempfile.mkdtemp()

    def init_app(app_):
        app_.config.update(
            CELERY_ALWAYS_EAGER=True,
            CELERY_CACHE_BACKEND='memory',
            CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
            CELERY_RESULT_BACKEND='cache',
            JSONSCHEMAS_URL_SCHEME='http',
            SECRET_KEY='CHANGE_ME',
            SECURITY_PASSWORD_SALT='CHANGE_ME_ALSO',
            SQLALCHEMY_DATABASE_URI=os.environ.get(
                'SQLALCHEMY_DATABASE_URI', 'sqlite:///test.db'),
            SQLALCHEMY_TRACK_MODIFICATIONS=True,
            SQLALCHEMY_ECHO=False,
            TESTING=True,
            WTF_CSRF_ENABLED=False,
            DEPOSIT_SEARCH_API='/api/search',
            SECURITY_PASSWORD_HASH='plaintext',
            SECURITY_PASSWORD_SCHEMES=['plaintext'],
            SECURITY_DEPRECATED_PASSWORD_SCHEMES=[],
            OAUTHLIB_INSECURE_TRANSPORT=True,
            OAUTH2_CACHE_TYPE='simple',
            ACCOUNTS_JWT_ENABLE=False,
        )
        Babel(app_)
        FlaskCeleryExt(app_)
        Breadcrumbs(app_)
        OAuth2Provider(app_)
        InvenioDB(app_)
        InvenioAccounts(app_)
        InvenioAccess(app_)
        InvenioIndexer(app_)
        InvenioJSONSchemas(app_)
        InvenioOAuth2Server(app_)
        InvenioFilesREST(app_)
        InvenioPIDStore(app_)
        InvenioRecords(app_)
        search = InvenioSearch(app_)
        search.register_mappings('deposits', 'invenio_deposit.mappings')

    api_app = Flask('testapiapp', instance_path=instance_path)
    api_app.url_map.converters['pid'] = PIDConverter
    # initialize InvenioDeposit first in order to detect any invalid dependency
    InvenioDepositREST(api_app)

    init_app(api_app)
    InvenioREST(api_app)
    InvenioOAuth2ServerREST(api_app)
    InvenioRecordsREST(api_app)

    app = Flask('testapp', instance_path=instance_path)
    app.url_map.converters['pid'] = PIDConverter
    # initialize InvenioDeposit first in order to detect any invalid dependency
    InvenioDeposit(app)
    init_app(app)
    app.register_blueprint(accounts_blueprint)
    app.register_blueprint(oauth2server_settings_blueprint)
    InvenioAssets(app)
    InvenioSearchUI(app)
    InvenioRecordsUI(app)
    app.register_blueprint(records_ui_bp(app))
    app.register_blueprint(records_rest_bp(app))
    app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
        '/api': api_app.wsgi_app
    })

    with app.app_context():
        if str(db.engine.url) != 'sqlite://' and \
           not database_exists(str(db.engine.url)):
            create_database(str(db.engine.url))
        db.create_all()

    yield app

    with app.app_context():
        if str(db.engine.url) != 'sqlite://':
            drop_database(str(db.engine.url))
        shutil.rmtree(instance_path)
Ejemplo n.º 27
0
# Set jinja loader to first grab templates from the app's folder.
app.jinja_loader = jinja2.ChoiceLoader([
    jinja2.FileSystemLoader(join(dirname(__file__), "templates")),
    app.jinja_loader
])

InvenioDB(app)
InvenioTheme(app)
InvenioJSONSchemas(app)
InvenioAccounts(app)
InvenioRecords(app)
InvenioRecordsUI(app)
search = InvenioSearch(app)
# search.register_mappings('testrecords', 'data')
InvenioSearchUI(app)
InvenioREST(app)
InvenioIndexer(app)
InvenioPIDStore(app)
InvenioAdmin(app)
InvenioOAuth2Server(app)

InvenioRecordsREST(app)
InvenioFilesREST(app)

assets = InvenioAssets(app)
assets.env.register('invenio_search_ui_search_js', js)

InvenioDeposit(app)
InvenioDepositREST(app)

app.register_blueprint(accounts_blueprint)
Ejemplo n.º 28
0
def app(request, search_class):
    """Flask application fixture.

    Note that RECORDS_REST_ENDPOINTS is used during application creation to
    create blueprints on the fly, hence once you have this fixture in a test,
    it's too late to customize the configuration variable. You can however
    customize it using parameterized tests:

    .. code-block:: python

    @pytest.mark.parametrize('app', [dict(
        endpoint=dict(
            search_class='conftest:TestSearch',
        )
    def test_mytest(app, db, es):
        # ...

    This will parameterize the default 'recid' endpoint in
    RECORDS_REST_ENDPOINTS.

    Alternatively:

    .. code-block:: python

    @pytest.mark.parametrize('app', [dict(
        records_rest_endpoints=dict(
            recid=dict(
                search_class='conftest:TestSearch',
            )
        )
    def test_mytest(app, db, es):
        # ...

    This will fully parameterize RECORDS_REST_ENDPOINTS.
    """
    instance_path = tempfile.mkdtemp()
    app = Flask('testapp', instance_path=instance_path)
    app.config.update(
        ACCOUNTS_JWT_ENABLE=False,
        INDEXER_DEFAULT_DOC_TYPE='testrecord',
        INDEXER_DEFAULT_INDEX=search_class.Meta.index,
        RECORDS_REST_ENDPOINTS=copy.deepcopy(config.RECORDS_REST_ENDPOINTS),
        RECORDS_REST_DEFAULT_CREATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_DELETE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_READ_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_UPDATE_PERMISSION_FACTORY=None,
        RECORDS_REST_DEFAULT_SEARCH_INDEX=search_class.Meta.index,
        RECORDS_REST_FACETS={
            search_class.Meta.index: {
                'aggs': {
                    'stars': {
                        'terms': {
                            'field': 'stars'
                        }
                    }
                },
                'post_filters': {
                    'stars': terms_filter('stars'),
                }
            }
        },
        RECORDS_REST_SORT_OPTIONS={
            search_class.Meta.index: dict(year=dict(fields=['year'], ))
        },
        SERVER_NAME='localhost:5000',
        SQLALCHEMY_DATABASE_URI=os.environ.get('SQLALCHEMY_DATABASE_URI',
                                               'sqlite:///test.db'),
        SQLALCHEMY_TRACK_MODIFICATIONS=True,
        TESTING=True,
    )
    app.config['RECORDS_REST_ENDPOINTS']['recid']['search_class'] = \
        search_class

    # Parameterize application.
    if hasattr(request, 'param'):
        if 'endpoint' in request.param:
            app.config['RECORDS_REST_ENDPOINTS']['recid'].update(
                request.param['endpoint'])
        if 'records_rest_endpoints' in request.param:
            original_endpoint = app.config['RECORDS_REST_ENDPOINTS']['recid']
            del app.config['RECORDS_REST_ENDPOINTS']['recid']
            for new_endpoint_prefix, new_endpoint_value in \
                    request.param['records_rest_endpoints'].items():
                new_endpoint = dict(original_endpoint)
                new_endpoint.update(new_endpoint_value)
                app.config['RECORDS_REST_ENDPOINTS'][new_endpoint_prefix] = \
                    new_endpoint

    app.url_map.converters['pid'] = PIDConverter

    InvenioDB(app)
    InvenioREST(app)
    InvenioRecords(app)
    InvenioIndexer(app)
    InvenioPIDStore(app)
    search = InvenioSearch(app)
    search.register_mappings(search_class.Meta.index, 'mock_module.mappings')
    InvenioRecordsREST(app)

    with app.app_context():
        yield app

    # Teardown instance path.
    shutil.rmtree(instance_path)
Ejemplo n.º 29
0
def app(base_app):
    """Flask application fixture."""

    base_app._internal_jsonschemas = InvenioJSONSchemas(base_app)
    InvenioREST(base_app)
    InvenioRecordsREST(base_app)
    InvenioRecords(base_app)
    InvenioPIDStore(base_app)
    base_app.url_map.converters['pid'] = PIDConverter
    OARepoValidate(base_app)
    SampleExt(base_app)

    try:
        from invenio_files_rest.ext import InvenioFilesREST
        from invenio_records_files.ext import InvenioRecordsFiles

        InvenioFilesREST(base_app)
        InvenioRecordsFiles(base_app)
    except ImportError:
        pass

    base_app.register_blueprint(
        invenio_records_rest.views.create_blueprint_from_app(base_app))

    principal = Principal(base_app)

    login_manager = LoginManager()
    login_manager.init_app(base_app)
    login_manager.login_view = 'login'

    @login_manager.user_loader
    def basic_user_loader(user_id):
        user_obj = User.query.get(int(user_id))
        return user_obj

    @base_app.route('/test/login/<int:id>', methods=['GET', 'POST'])
    def test_login(id):
        print("test: logging user with id", id)
        response = make_response()
        user = User.query.get(id)
        print('User is', user)
        login_user(user)
        set_identity(user)
        return response

    @base_app.route('/test/logout', methods=['GET', 'POST'])
    def test_logout():
        print("test: logging out")
        response = make_response()
        logout_user()

        # Remove session keys set by Flask-Principal
        for key in ('identity.name', 'identity.auth_type'):
            session.pop(key, None)

        # Tell Flask-Principal the user is anonymous
        identity_changed.send(current_app._get_current_object(),
                              identity=AnonymousIdentity())

        return response

    app_loaded.send(None, app=base_app)

    with base_app.app_context():
        yield base_app