Ejemplo n.º 1
0
def create_app():
	app = Flask(__name__)
	app.config.from_pyfile('config.py')

	cache.init_app(app, config=app.config['CACHE_CONFIG'])
	cors.init_app(app, origins=app.config['ALLOWED_ORIGINS'])
	db.init_app(app)
	migrate.init_app(app, db)

	scheduler.init_app(app)
	scheduler.start()

	authenticator = HeaderApiKeyAuthenticator(header=app.config['AUTH_HEADER'])
	authenticator.register_key(key=app.config['AUTH_KEY'],
							   app_name=app.config['AUTH_ALLOWED_CLIENT'])
	registry.set_default_authenticator(authenticator)

	# IMPORTANT: import the views before rebar initialisation
	from backend.example.endpoints import get_user
	rebar.init_app(app)

	# suppress werkzeug logging (see README)
	log = logging.getLogger('werkzeug')
	log.setLevel(logging.ERROR)

	# log with our app logger
	@app.after_request
	def log_request(response):
		app.logger.info(response.status)
		return response

	return app
Ejemplo n.º 2
0
def create_app(name):
    app = Flask(name)

    authenticator = HeaderApiKeyAuthenticator(header="X-MyApp-Key")
    # The HeaderApiKeyAuthenticator does super simple authentication, designed for
    # service-to-service authentication inside of a protected network, by looking for a
    # shared secret in the specified header. Here we define what that shared secret is.
    authenticator.register_key(key="my-api-key")
    registry.set_default_authenticator(authenticator=authenticator)

    rebar.init_app(app=app)

    return app
Ejemplo n.º 3
0
def register_multiple_authenticators(registry):
    default_authenticator = HeaderApiKeyAuthenticator(
        header=DEFAULT_AUTH_HEADER, name="default")
    default_authenticator.register_key(app_name="internal",
                                       key=DEFAULT_AUTH_SECRET)
    alternative_default_authenticator = HeaderApiKeyAuthenticator(
        header=DEFAULT_ALTERNATIVE_AUTH_HEADER, name="alternative")
    alternative_default_authenticator.register_key(
        app_name="internal", key=DEFAULT_ALTERNATIVE_AUTH_SECRET)
    registry.set_default_authenticators(
        (default_authenticator, alternative_default_authenticator))
Ejemplo n.º 4
0
    def test_override_authenticator(self):
        auth_header = 'x-overridden-auth'
        auth_secret = 'BLAM!'

        rebar = Rebar()
        registry = rebar.create_handler_registry()

        register_default_authenticator(registry)
        authenticator = HeaderApiKeyAuthenticator(header=auth_header)
        authenticator.register_key(app_name='internal', key=auth_secret)

        register_endpoint(registry, authenticator=authenticator)
        app = create_rebar_app(rebar)

        resp = app.test_client().get(path='/foos/1',
                                     headers=auth_headers(header=auth_header,
                                                          secret=auth_secret))
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(get_json_from_resp(resp), DEFAULT_RESPONSE)

        # The default authentication doesn't work anymore!
        resp = app.test_client().get(path='/foos/1', headers=auth_headers())
        self.assertEqual(resp.status_code, 401)
Ejemplo n.º 5
0
import marshmallow as m

from flask_rebar import Rebar
from flask_rebar import HeaderApiKeyAuthenticator
from flask_rebar import compat
from flask_rebar.swagger_generation import SwaggerV2Generator, SwaggerV3Generator

rebar = Rebar()
registry = rebar.create_handler_registry()

swagger_v2_generator = SwaggerV2Generator()
swagger_v3_generator_with_hidden = SwaggerV3Generator(include_hidden=True)
normal_swagger_v3_generator = SwaggerV3Generator()

authenticator = HeaderApiKeyAuthenticator(header="x-auth")
default_authenticator = HeaderApiKeyAuthenticator(header="x-another", name="default")


class HeaderSchema(m.Schema):
    user_id = compat.set_data_key(field=m.fields.String(required=True), key="X-UserId")


class FooSchema(m.Schema):
    __swagger_title__ = "Foo"

    uid = m.fields.String()
    name = m.fields.String()


class NestedFoosSchema(m.Schema):
    data = m.fields.Nested(FooSchema, many=True)
Ejemplo n.º 6
0
def register_default_authenticator(registry):
    default_authenticator = HeaderApiKeyAuthenticator(
        header=DEFAULT_AUTH_HEADER, name='default')
    default_authenticator.register_key(app_name='internal',
                                       key=DEFAULT_AUTH_SECRET)
    registry.set_default_authenticator(default_authenticator)
    def get_security_requirements(self, instance, context):
        return [{
            "openIDConnect": instance.required_scopes,
            "application_key": []
        }]


authenticator_converter_registry.register_types([
    HeaderApiKeyConverter(),
    HTTPAuthorizationAuthenticatorConverter(),
    OAuth2AuthenticatorConverter(),
    ComplexAuthenticatorConverter(),
])

default_authenticator = FakeOAuth2Authenticator(required_scopes=["read:stuff"])
alternative_default_authenticator = HeaderApiKeyAuthenticator(
    header="x-api-key")

authenticator = FakeHTTPAuthorizationAuthenticator()
alternative_authenticator = FakeComplexAuthenticator(
    header="x-app-id",
    url="https://exmaple.com/openconnect",
    required_scopes=["write:junk", "write:stuff"],
)

customer_authenticator_converter_registry = [
    HTTPAuthorizationAuthenticatorConverter(),
    OAuth2AuthenticatorConverter(),
    ComplexAuthenticatorConverter(),
]

    def test_generate_swagger(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        authenticator = HeaderApiKeyAuthenticator(header='x-auth')
        default_authenticator = HeaderApiKeyAuthenticator(header='x-another',
                                                          name='default')

        class HeaderSchema(m.Schema):
            user_id = m.fields.String(load_from='x-userid', required=True)

        class FooSchema(m.Schema):
            __swagger_title__ = 'Foo'

            uid = m.fields.String()
            name = m.fields.String()

        class ListOfFooSchema(m.Schema):
            data = m.fields.Nested(FooSchema, many=True)

        class FooUpdateSchema(m.Schema):
            __swagger_title = 'FooUpdate'

            name = m.fields.String()

        class FooListSchema(m.Schema):
            name = m.fields.String()

        @registry.handles(rule='/foos/<uuid_string:foo_uid>',
                          method='GET',
                          marshal_schema={200: FooSchema()},
                          headers_schema=HeaderSchema())
        def get_foo(foo_uid):
            """helpful description"""
            pass

        @registry.handles(rule='/foos/<foo_uid>',
                          method='PATCH',
                          marshal_schema={200: FooSchema()},
                          request_body_schema=FooUpdateSchema(),
                          authenticator=authenticator)
        def update_foo(foo_uid):
            pass

        @registry.handles(
            rule='/foos',
            method='GET',
            marshal_schema={200: ListOfFooSchema()},
            query_string_schema=FooListSchema(),
            authenticator=None  # Override the default!
        )
        def list_foos():
            pass

        registry.set_default_authenticator(default_authenticator)

        host = 'swag.com'
        schemes = ['http']
        consumes = ['application/json']
        produces = ['application/vnd.plangrid+json']
        title = 'Test API'
        version = '2.1.0'

        class Error(m.Schema):
            message = m.fields.String()
            details = m.fields.Dict()

        generator = SwaggerV2Generator(host=host,
                                       schemes=schemes,
                                       consumes=consumes,
                                       produces=produces,
                                       title=title,
                                       version=version,
                                       default_response_schema=Error())

        swagger = generator.generate(registry)

        expected_swagger = {
            'swagger': '2.0',
            'host': host,
            'info': {
                'title': title,
                'version': version,
                'description': '',
            },
            'schemes': schemes,
            'consumes': consumes,
            'produces': produces,
            'security': [{
                'default': []
            }],
            'securityDefinitions': {
                'sharedSecret': {
                    'type': 'apiKey',
                    'in': 'header',
                    'name': 'x-auth'
                },
                'default': {
                    'type': 'apiKey',
                    'in': 'header',
                    'name': 'x-another'
                }
            },
            'paths': {
                '/foos/{foo_uid}': {
                    'parameters': [{
                        'name': 'foo_uid',
                        'in': 'path',
                        'required': True,
                        'type': 'string'
                    }],
                    'get': {
                        'operationId':
                        'get_foo',
                        'description':
                        'helpful description',
                        'responses': {
                            '200': {
                                'description': 'Foo',
                                'schema': {
                                    '$ref': '#/definitions/Foo'
                                }
                            },
                            'default': {
                                'description': 'Error',
                                'schema': {
                                    '$ref': '#/definitions/Error'
                                }
                            }
                        },
                        'parameters': [{
                            'name': 'x-userid',
                            'in': 'header',
                            'required': True,
                            'type': 'string'
                        }]
                    },
                    'patch': {
                        'operationId':
                        'update_foo',
                        'responses': {
                            '200': {
                                'description': 'Foo',
                                'schema': {
                                    '$ref': '#/definitions/Foo'
                                }
                            },
                            'default': {
                                'description': 'Error',
                                'schema': {
                                    '$ref': '#/definitions/Error'
                                }
                            }
                        },
                        'parameters': [{
                            'name': 'FooUpdateSchema',
                            'in': 'body',
                            'required': True,
                            'schema': {
                                '$ref': '#/definitions/FooUpdateSchema'
                            }
                        }],
                        'security': [{
                            'sharedSecret': []
                        }]
                    }
                },
                '/foos': {
                    'get': {
                        'operationId':
                        'list_foos',
                        'responses': {
                            '200': {
                                'description': 'ListOfFooSchema',
                                'schema': {
                                    '$ref': '#/definitions/ListOfFooSchema'
                                }
                            },
                            'default': {
                                'description': 'Error',
                                'schema': {
                                    '$ref': '#/definitions/Error'
                                }
                            }
                        },
                        'parameters': [{
                            'name': 'name',
                            'in': 'query',
                            'required': False,
                            'type': 'string'
                        }],
                        'security': []
                    }
                }
            },
            'definitions': {
                'Foo': {
                    'type': 'object',
                    'title': 'Foo',
                    'properties': {
                        'uid': {
                            'type': 'string'
                        },
                        'name': {
                            'type': 'string'
                        }
                    }
                },
                'FooUpdateSchema': {
                    'type': 'object',
                    'title': 'FooUpdateSchema',
                    'properties': {
                        'name': {
                            'type': 'string'
                        }
                    }
                },
                'ListOfFooSchema': {
                    'type': 'object',
                    'title': 'ListOfFooSchema',
                    'properties': {
                        'data': {
                            'type': 'array',
                            'items': {
                                '$ref': '#/definitions/Foo'
                            }
                        }
                    }
                },
                'Error': {
                    'type': 'object',
                    'title': 'Error',
                    'properties': {
                        'message': {
                            'type': 'string'
                        },
                        'details': {
                            'type': 'object'
                        }
                    }
                }
            }
        }

        # Uncomment these lines to just dump the result to the terminal:

        # import json
        # print(json.dumps(swagger, indent=2))
        # self.assertTrue(False)

        # This will raise an error if validation fails
        validate_swagger(expected_swagger)

        self.assertEqual(swagger, expected_swagger)
import marshmallow as m

from flask_rebar import Rebar
from flask_rebar import HeaderApiKeyAuthenticator
from flask_rebar import compat
from flask_rebar.authenticators import USE_DEFAULT

rebar = Rebar()
registry = rebar.create_handler_registry()

authenticator = HeaderApiKeyAuthenticator(header="x-auth")
default_authenticator = HeaderApiKeyAuthenticator(header="x-another",
                                                  name="default")
alternative_default_authenticator = HeaderApiKeyAuthenticator(
    header="x-api", name="alternative")


class HeaderSchema(m.Schema):
    user_id = compat.set_data_key(field=m.fields.String(required=True),
                                  key="X-UserId")


class FooSchema(m.Schema):
    __swagger_title__ = "Foo"

    uid = m.fields.String()
    name = m.fields.String()


class NestedFoosSchema(m.Schema):
    data = m.fields.Nested(FooSchema, many=True)
Ejemplo n.º 10
0
    def test_generate_swagger(self):
        rebar = Rebar()
        registry = rebar.create_handler_registry()

        authenticator = HeaderApiKeyAuthenticator(header="x-auth")
        default_authenticator = HeaderApiKeyAuthenticator(
            header="x-another", name="default"
        )

        class HeaderSchema(m.Schema):
            user_id = compat.set_data_key(
                field=m.fields.String(required=True), key="X-UserId"
            )

        class FooSchema(m.Schema):
            __swagger_title__ = "Foo"

            uid = m.fields.String()
            name = m.fields.String()

        class NestedFoosSchema(m.Schema):
            data = m.fields.Nested(FooSchema, many=True)

        class FooUpdateSchema(m.Schema):
            __swagger_title = "FooUpdate"

            name = m.fields.String()

        class NameAndOtherSchema(m.Schema):
            name = m.fields.String()
            other = m.fields.String()

        @registry.handles(
            rule="/foos/<uuid_string:foo_uid>",
            method="GET",
            marshal_schema={200: FooSchema()},
            headers_schema=HeaderSchema(),
        )
        def get_foo(foo_uid):
            """helpful description"""
            pass

        @registry.handles(
            rule="/foos/<foo_uid>",
            method="PATCH",
            marshal_schema={200: FooSchema()},
            request_body_schema=FooUpdateSchema(),
            authenticator=authenticator,
        )
        def update_foo(foo_uid):
            pass

        # Test using Schema(many=True) without using a nested Field.
        # https://github.com/plangrid/flask-rebar/issues/41
        @registry.handles(
            rule="/foo_list",
            method="GET",
            marshal_schema={200: FooSchema(many=True)},
            authenticator=None,  # Override the default!
        )
        def list_foos():
            pass

        @registry.handles(
            rule="/foos",
            method="GET",
            marshal_schema={200: NestedFoosSchema()},
            query_string_schema=NameAndOtherSchema(),
            authenticator=None,  # Override the default!
        )
        def nested_foos():
            pass

        @registry.handles(rule="/tagged_foos", tags=["bar", "baz"])
        def tagged_foos():
            pass

        registry.set_default_authenticator(default_authenticator)

        host = "swag.com"
        schemes = ["http"]
        consumes = ["application/json"]
        produces = ["application/json"]
        title = "Test API"
        version = "2.1.0"

        class Error(m.Schema):
            message = m.fields.String()
            details = m.fields.Dict()

        generator = SwaggerV2Generator(
            host=host,
            schemes=schemes,
            consumes=consumes,
            produces=produces,
            title=title,
            version=version,
            default_response_schema=Error(),
            tags=[
                Tag(
                    name="bar",
                    description="baz",
                    external_docs=ExternalDocumentation(
                        url="http://bardocs.com", description="qux"
                    ),
                )
            ],
        )

        swagger = generator.generate(registry)

        expected_swagger = {
            "swagger": "2.0",
            "host": host,
            "info": {"title": title, "version": version, "description": ""},
            "schemes": schemes,
            "consumes": consumes,
            "produces": produces,
            "security": [{"default": []}],
            "securityDefinitions": {
                "sharedSecret": {"type": "apiKey", "in": "header", "name": "x-auth"},
                "default": {"type": "apiKey", "in": "header", "name": "x-another"},
            },
            "tags": [
                {
                    "name": "bar",
                    "description": "baz",
                    "externalDocs": {"url": "http://bardocs.com", "description": "qux"},
                }
            ],
            "paths": {
                "/foos/{foo_uid}": {
                    "parameters": [
                        {
                            "name": "foo_uid",
                            "in": "path",
                            "required": True,
                            "type": "string",
                        }
                    ],
                    "get": {
                        "operationId": "get_foo",
                        "description": "helpful description",
                        "responses": {
                            "200": {
                                "description": "Foo",
                                "schema": {"$ref": "#/definitions/Foo"},
                            },
                            "default": {
                                "description": "Error",
                                "schema": {"$ref": "#/definitions/Error"},
                            },
                        },
                        "parameters": [
                            {
                                "name": "X-UserId",
                                "in": "header",
                                "required": True,
                                "type": "string",
                            }
                        ],
                    },
                    "patch": {
                        "operationId": "update_foo",
                        "responses": {
                            "200": {
                                "description": "Foo",
                                "schema": {"$ref": "#/definitions/Foo"},
                            },
                            "default": {
                                "description": "Error",
                                "schema": {"$ref": "#/definitions/Error"},
                            },
                        },
                        "parameters": [
                            {
                                "name": "FooUpdateSchema",
                                "in": "body",
                                "required": True,
                                "schema": {"$ref": "#/definitions/FooUpdateSchema"},
                            }
                        ],
                        "security": [{"sharedSecret": []}],
                    },
                },
                "/foo_list": {
                    "get": {
                        "operationId": "list_foos",
                        "responses": {
                            "200": {
                                "description": "Foo",
                                "schema": {
                                    "type": "array",
                                    "items": {"$ref": "#/definitions/Foo"},
                                },
                            },
                            "default": {
                                "description": "Error",
                                "schema": {"$ref": "#/definitions/Error"},
                            },
                        },
                        "security": [],
                    }
                },
                "/foos": {
                    "get": {
                        "operationId": "nested_foos",
                        "responses": {
                            "200": {
                                "description": "NestedFoosSchema",
                                "schema": {"$ref": "#/definitions/NestedFoosSchema"},
                            },
                            "default": {
                                "description": "Error",
                                "schema": {"$ref": "#/definitions/Error"},
                            },
                        },
                        "parameters": [
                            {
                                "name": "name",
                                "in": "query",
                                "required": False,
                                "type": "string",
                            },
                            {
                                "name": "other",
                                "in": "query",
                                "required": False,
                                "type": "string",
                            },
                        ],
                        "security": [],
                    }
                },
                "/tagged_foos": {
                    "get": {
                        "tags": ["bar", "baz"],
                        "operationId": "tagged_foos",
                        "responses": {
                            "default": {
                                "description": "Error",
                                "schema": {"$ref": "#/definitions/Error"},
                            }
                        },
                    }
                },
            },
            "definitions": {
                "Foo": {
                    "type": "object",
                    "title": "Foo",
                    "properties": {
                        "uid": {"type": "string"},
                        "name": {"type": "string"},
                    },
                },
                "FooUpdateSchema": {
                    "type": "object",
                    "title": "FooUpdateSchema",
                    "properties": {"name": {"type": "string"}},
                },
                "NestedFoosSchema": {
                    "type": "object",
                    "title": "NestedFoosSchema",
                    "properties": {
                        "data": {
                            "type": "array",
                            "items": {"$ref": "#/definitions/Foo"},
                        }
                    },
                },
                "Error": {
                    "type": "object",
                    "title": "Error",
                    "properties": {
                        "message": {"type": "string"},
                        "details": {"type": "object"},
                    },
                },
            },
        }

        # Uncomment these lines to just dump the result to the terminal:

        # import json
        # print(json.dumps(swagger, indent=2))
        # print(json.dumps(expected_swagger, indent=2))
        # self.assertTrue(False)

        # This will raise an error if validation fails
        validate_swagger(expected_swagger)

        self.assertEqual(swagger, expected_swagger)
Ejemplo n.º 11
0
# -*- coding: utf-8 -*-
""" REST API - Endpoint routing

    Author(s): Adam Mitchell, [email protected]
"""
from flask import current_app, request
from flask_rebar import HeaderApiKeyAuthenticator, Rebar, response

from rest_api.schemas import *

authenticator = HeaderApiKeyAuthenticator(header='X-MyApp-ApiKey')
authenticator.register_key(key='my-super-secret-key')

rebar = Rebar()
registry = rebar.create_handler_registry()


@registry.handles(rule='/generic_greeting',
                  method='GET',
                  marshal_schema={200: GetGenericGreetingSchema()},
                  authenticator=authenticator)
def getGenericGreeting():
    return ({'message': 'Hello, Generic Person!'}, 200)


@registry.handles(rule='/personalised_greeting',
                  method='GET',
                  marshal_schema={200: GetGenericGreetingSchema()},
                  query_string_schema=GetPersonalisedGreetingSchema(),
                  authenticator=authenticator)
def getPersonalisedGreeting():