Exemplo n.º 1
0
def test_context_manager_component(app_cls):
    log = []

    class ContextManagerComponent():
        def __init__(self, method: http.Method, path: http.Path) -> None:
            pass

        def __enter__(self):
            nonlocal log
            log.append('context manager enter')

        def __exit__(self, *args, **kwargs):
            nonlocal log
            log.append('context manager exit')

    def view(c: ContextManagerComponent):
        nonlocal log
        log.append('view')
        return

    routes = [Route('/', 'GET', view)]
    components = [Component(ContextManagerComponent)]
    app = app_cls(routes=routes, components=components)
    client = TestClient(app)
    client.get('/')
    assert log == ['context manager enter', 'view', 'context manager exit']
Exemplo n.º 2
0
def app_fix():
    """
    fixture for apistar app
    Juste mock get_session to get_ss to disable db stuff from apistar
    Use all regular routes and componements of app.py
    All
    """
    comp = []
    for c in components:
        if c.cls is Session:
            c = Component(Session, init=get_ss, preload=False)
        comp.append(c)
    return App(routes=routes, settings=settings, components=comp)
Exemplo n.º 3
0
def test_component_injected_twice_runs_once(app_cls):
    log = []

    class LoggingComponent():
        def __init__(self, method: http.Method, path: http.Path) -> None:
            nonlocal log
            log.append('logging component injected')

    def view(a: LoggingComponent, b: LoggingComponent):
        return

    routes = [Route('/', 'GET', view)]
    components = [Component(LoggingComponent)]
    app = app_cls(routes=routes, components=components)
    client = TestClient(app)
    client.get('/')
    assert log == ['logging component injected']
Exemplo n.º 4
0
def test_jwt_as_component(app_class) -> None:
    routes = [
        Route('/as-a-component-route', 'GET', injected_component),
    ]
    settings = {
        'JWT': {
            'SECRET': 'jwt-secret',
            'USERNAME': '******',
            'ID': 'user',
        }
    }
    components = [
        Component(JWT, init=get_jwt)
    ]

    app = app_class(routes=routes, settings=settings, components=components)
    client = TestClient(app)

    payload = {'user': 1, 'username': '******'}
    secret = settings['JWT']['SECRET']
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
    assert response.json() == payload

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer ',
    })
    assert response.status_code == 401

    # wrong secret
    encoded_jwt = jwt.encode(payload, 'wrong secret', algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    # wrong algorithm
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS512').decode(encoding='UTF-8')
    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401
Exemplo n.º 5
0
    Run the Postgresql shell with this projects DB settings
    """
    psql = ['psql']
    env = os.environ.copy()

    if backend.url:
        # Prefer the url
        psql.append(backend.url)
    else:
        # Build a command line from the config.
        # Put the password in the environment with PGPASS
        config = backend.config
        env['DBPASSWORD'] = config.get('PASSWORD', '')

        keys = set(config.keys()) & set(backend.CLI_CONFIG_MAP.keys())
        for k in keys:
            psql.append(backend.CLI_CONFIG_MAP[k])
            psql.append(config[k])

    subprocess.call(psql, env=env)


components = [
    Component(AsyncPgBackend, init=AsyncPgBackend),
    Component(Connection, init=get_conn, preload=False),
]

commands = [
    Command('dbshell', pg_cli),
]
Exemplo n.º 6
0
def redis_cli(redis_cache: Redis):
    """
    Run the Redis cli with the project Redis connection settings
    """
    loop = asyncio.get_event_loop()
    conn_info = loop.run_until_complete(redis_cache.conn_info())

    args = ['redis-cli', '-n', f"{conn_info.get('db', 0)}"]

    if isinstance(conn_info['address'], str):
        args += ['-s', conn_info['address']]
    else:
        args += [
            '-h', conn_info['address'][0], '-p',
            str(conn_info['address'][1])
        ]

    if redis_cache.config.get('password'):
        args += ['-a', redis_cache.config.get('password')]

    logger.debug('REDIS CLI: %s', ' '.join(args))
    subprocess.call(args)


components = [
    Component(Redis, init=Redis),
]

commands = [Command('redis_cli', redis_cli)]
Exemplo n.º 7
0
from urllib.parse import quote_plus
from apistar import Component, Settings
from pymongo import MongoClient
from pymongo.database import Database


__mongo = None
def init_mongo(settings: Settings):
    global __mongo
    if __mongo is None:
        mongo_uri = "mongodb://{user}:{password}@{host}".format(
            user=quote_plus(settings['MONGO']['user']),
            password=quote_plus(settings['MONGO']['password']),
            host=settings['MONGO']['host'],
        )
        __mongo = MongoClient(mongo_uri).abigale
    return __mongo

MongoDB = Component(Database, init=init_mongo)
Exemplo n.º 8
0
# -*- coding: utf-8 -*-
"""APIStar Web App."""

import sys
import apistar_peewee  # https://github.com/aachurin/apistar_peewee
from apistar.frameworks.wsgi import WSGIApp as App

from routes import routes
from settings import settings
from apistar import Component
from apistar_jwt.authentication import get_jwt
from apistar_jwt.token import JWT

__version__ = "1.0.0"
__license__ = "???"
__author__ = "???"
__email__ = "*****@*****.**"
__url__ = "https://example.com"

sys.dont_write_bytecode = settings.get("DONT_WRITE_BYTECODE", True)  # No *.PYC

app: App = App(
    routes=routes,
    settings=settings,
    commands=apistar_peewee.commands,  # Install custom commands.
    components=apistar_peewee.components + [Component(JWT, init=get_jwt)],
)

if __name__ in '__main__':
    app.main()
Exemplo n.º 9
0
        self.close()


class Session(object):
    """
    Class responsible to hold a mongodb session instance
    """
    def __init__(self, backend: MongoBackend) -> None:
        self.db = backend.client[backend.database_name]
        for model in registered_collections:
            setattr(self, model['collection'], self.db[model['collection']])


@contextlib.contextmanager
def get_session(
        backend: MongoBackend) -> typing.Generator[Session, None, None]:
    """
    Create a new context-managed database session for mongodb
    """
    backend.connect()

    yield Session(backend)

    backend.close()


components = [
    Component(MongoBackend),
    Component(Session, init=get_session, preload=False),
]
Exemplo n.º 10
0
        self.custom_function = config.get('CUSTOM_FUNCTION')
        self.header = config.get('HEADER', 'Shell')

    def get_custom_imports(self):
        module = import_module(self.custom_function['module'])
        function = import_class(module, self.custom_function['function'])
        return function()

    def get_namespace(self):
        namespace = {}
        for item in self.imports:
            module_name = item.get('module')
            module = import_module(item.get('module'))
            imports = item.get('imports')

            if not imports:
                namespace[module_name] = module
            else:
                for klass in imports:
                    namespace[klass] = import_class(module, klass)

        if self.custom_function:
            namespace.update(self.get_custom_imports())

        return namespace


components = [
    Component(ShellBackend),
]
Exemplo n.º 11
0
    @classmethod
    def set_headers(cls, headers={}):
        # A funny factory to get an instance with preset headers that are included
        # in every requests. This makes it easy to get a new instance while keeping
        # it's usage with the Component pattern easy.
        return cls(headers=headers)

    @mergeargs
    async def get(self, *args, **kwargs):
        logger.debug("AIOClient get")
        resp = await self._session.get(*args, **kwargs)

        logger.debug("AIOClient get resp: %s", resp)
        #  logger.debug("AIOClient get resp: %s", dir(resp))

        return resp

    @mergeargs
    async def post(self, *args, **kwargs):
        logger.debug("AIOClient post")
        resp = await self._session.post(*args, **kwargs)

        logger.debug("AIOClient post resp: %s", resp)
        #  logger.debug("AIOClient post resp: %s", dir(resp))

        return resp


components = [Component(Client, init=Client)]
from cadastre import sql

from sqlalchemy import Column, String, ForeignKey

class ApiToken(sql.Base):
    __tablename__ = 'api_token'
    id = Column(String, primary_key = True)
    email = Column(String,
        ForeignKey('user.email'),
        nullable = False,
    )
    token = Column(String, unique = True, nullable = False)
    description = Column(String, nullable = False)


# ## COMPONENTS

# The repository for a request can be made available as a component, relying on
# the SQLAlchemy session component for the same request.

from apistar.backends.sqlalchemy_backend import Session

def request_repository(session: Session):
    return Repository(session)

from apistar import Component

components = [
    Component(Repository, init = request_repository, preload = False),
]
Exemplo n.º 13
0
import os
import tempfile

import pytest

from apistar import Component, exceptions
from apistar.components.console import BufferConsole
from apistar.frameworks.wsgi import WSGIApp as App
from apistar.interfaces import Console

components = [Component(Console, init=BufferConsole)]
app = App(components=components)


def test_new():
    with tempfile.TemporaryDirectory() as tempdir:
        os.chdir(tempdir)
        app.main(['new', 'myproject', '--framework', 'wsgi'],
                 standalone_mode=False)
        assert os.path.exists('myproject')
        assert os.path.exists(os.path.join('myproject', 'app.py'))
        assert os.path.exists(os.path.join('myproject', 'tests.py'))
    assert app.console.buffer.splitlines() == [
        'myproject/app.py', 'myproject/tests.py'
    ]


def test_do_not_overwrite_existing_project():
    with tempfile.TemporaryDirectory() as tempdir:
        os.chdir(tempdir)
        app.main(['new', 'myproject', '--framework', 'wsgi'],
Exemplo n.º 14
0
def test_jwt_issuer_claim(app_class) -> None:
    routes = [
        Route('/as-a-component-route', 'GET', injected_component),
        Route('/auth-required-route', 'GET', auth_required),
    ]
    settings = {
        'JWT': {
            'SECRET': 'jwt-secret',
            'USERNAME': '******',
            'ID': 'user',
            'ISSUER': 'urn:foo',
        }
    }
    components = [
        Component(JWT, init=get_jwt)
    ]

    app = app_class(routes=routes, settings=settings, components=components)
    client = TestClient(app)

    payload = {'user': 1, 'username': '******', 'iss': 'urn:foo'}
    secret = settings['JWT']['SECRET']

    # iss claim is correct
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
    assert response.json() == {'id': payload[settings['JWT']['ID']], 'name': payload[settings['JWT']['USERNAME']]}  # noqa; E501

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
    assert response.json() == payload

    # iss claim is incorrect
    payload['iss'] = 'urn:not-foo'
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    # no iss claim included in jwt
    del payload['iss']
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401
Exemplo n.º 15
0
def test_jwt_leeway_claim(app_class) -> None:
    routes = [
        Route('/as-a-component-route', 'GET', injected_component),
        Route('/auth-required-route', 'GET', auth_required),
    ]
    settings = {
        'JWT': {
            'SECRET': 'jwt-secret',
            'USERNAME': '******',
            'ID': 'user',
            'LEEWAY': 3,
        }
    }
    components = [
        Component(JWT, init=get_jwt)
    ]

    app = app_class(routes=routes, settings=settings, components=components)
    client = TestClient(app)

    payload = {'user': 1, 'username': '******', 'exp': datetime.utcnow() - timedelta(seconds=2)}
    secret = settings['JWT']['SECRET']

    # exp claim doesn't fail because of leeway
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
    assert response.json() == {'id': payload[settings['JWT']['ID']], 'name': payload[settings['JWT']['USERNAME']]}  # noqa; E501

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
    assert response.json() == payload

    # exp claim fails because leeway is only 3 seconds
    payload['exp'] = datetime.utcnow() - timedelta(seconds=4)
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 401

    # no exp claim included in jwt, leeway doesnt apply
    del payload['exp']
    encoded_jwt = jwt.encode(payload, secret, algorithm='HS256').decode(encoding='UTF-8')
    response = client.get('/auth-required-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200

    response = client.get('/as-a-component-route', headers={
        'Authorization': 'Bearer {token}'.format(token=encoded_jwt),
    })
    assert response.status_code == 200
Exemplo n.º 16
0

def login(username: str, session: http.Session) -> dict:
    session["username"] = username or getuser()            # Writes FAKE Data.
    session["last_login"] = datetime.utcnow().isoformat()  # Writes FAKE Data.
    session["token"] = token_urlsafe()                     # Writes FAKE Data.
    print(session.data)                                    # Reads Session Data.
    return session.data


def logout(session: http.Session) -> dict:
    if session.data:  # Clean out Session Data.
        del session["username"], session["last_login"], session["token"]
    return session.data


routes = (
    Route('/', 'GET', login),          # Writes and Reads Session Data.
    Route('/logout', 'GET', logout),   # Deletes Session Data.
)


cookie_sessions = (Component(http.Session, init=init_cookie_session), )


app = App(routes=routes, components=cookie_sessions)


if __name__ in '__main__':
    app.main()
Exemplo n.º 17
0
def create_tables(backend: SQLAlchemyBackend):
    """
    Create all database tables.

    Args:
      backend: The configured database backend.
    """
    backend.metadata.create_all(backend.engine)


def drop_tables(backend: SQLAlchemyBackend):
    """
    Drop all database tables.

    Args:
      backend: The configured database backend.
    """
    backend.metadata.drop_all(backend.engine)


components = [
    Component(SQLAlchemyBackend),
    Component(Session, init=get_session, preload=False)
]

commands = [
    Command('create_tables', create_tables),
    Command('drop_tables', drop_tables)
]
Exemplo n.º 18
0
async def get_app(settings: Settings = None):
    default_settings = {
        'DEBUG': True,
        'AUTHENTICATION': [],
        'QVARN': {
            'BACKEND': {
                'MODULE': 'qvarn.backends.postgresql',
                'USERNAME': '******',
                'PASSWORD': '******',
                'HOST': 'postgres',
                'PORT': None,
                'DBNAME': 'planb',
                'INITDB': True,
            },
            'RESOURCE_TYPES_PATH':
            '/etc/qvarn/resources',
            'TOKEN_ISSUER':
            'https://auth-jsonb.alpha.vaultit.org',
            'TOKEN_AUDIENCE':
            'http://localhost:8080',
            'TOKEN_SIGNING_KEY':
            ('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLDDFzdeGRZB1EOCWObzmjT34pLhLrSoU4WGu3u0IDhbaQleTQ6hTDj27DkFg20Q'
             'ux8PXxcXjxzJXq+ycQDOfDP5ET+/JVeFgPxlX7aQHWyi7g5kY4LNk5AiY6/F1lD/3j4jrdMbhGDfkm44o/ow52q+mU9bnciEeISn1E'
             'joDMH4ggk9gzZJDod6fTBwe+tkBETMMG08M9/5jgO4OE3lHBYF60EdMrSQ2kVRvUAOjmXGUyycn80g1BTAwy0SYX01MfGVgfGsSYJ/'
             'LKfbtXd5AXjmDXSC3SOsjf/9MdCZ07gNmDzqmyr4yVRJSfYdIn1Prw4BH+seVZmSQqapZ5D2hp'
             ),
        },
    }
    settings = merge(default_settings, settings or {})
    settings['AUTHENTICATION'] += [BearerAuthentication(settings)]
    settings['storage'] = await backends.init(settings)

    routes = []

    if settings['DEBUG']:
        routes += [
            Include('/docs', docs_urls),
            Include('/static', static_urls),
        ]

    routes += [
        Route('/version', 'GET', views.version),
        Route('/auth/token', 'POST', views.auth_token),
        Route('/{resource_type}', 'GET', views.resource_get),
        Route('/{resource_type}', 'POST', views.resource_post),
        Route('/{resource_type}/search/{query}', 'GET', views.resource_search),
        Route('/{resource_type}/{resource_id}', 'GET', views.resource_id_get),
        Route('/{resource_type}/{resource_id}', 'PUT', views.resource_id_put),
        Route('/{resource_type}/{resource_id}', 'DELETE',
              views.resource_id_delete),
        Route('/{resource_type}/{resource_id}/{subpath}', 'GET',
              views.resource_id_subpath_get),
        Route('/{resource_type}/{resource_id}/{subpath}', 'PUT',
              views.resource_id_subpath_put),
    ]

    commands = [
        Command('token-signing-key', token_signing_key),
    ]

    components = [
        Component(backends.Storage, init=backends.get_storage),
    ]

    return App(routes=routes,
               commands=commands,
               components=components,
               settings=settings)
Exemplo n.º 19
0
class DetectedMetadata(Metadata):
    pass

def detect_metadata(body: http.Body, content_type: http.Header):
    metadata_extractor = extractor_for_mime_type(content_type)
    return metadata_extractor(body)

# A request can provide metadata merged from `HeaderMetadata` and
# `DetectedMetadata`

class MergedMetadata(Metadata):
    pass

def merge_metadata(
    header_metadata: HeaderMetadata,
    detected_metadata: DetectedMetadata,
):
    return header_metadata.merge(detected_metadata)

# Using this canned component registration will allow an API Star application to
# extract various kinds of `Metadata` from requests using the request's headers.
# It allows injection of that `Metadata` into a service's arguments.

from apistar import Component

components = [
    Component(HeaderMetadata, init = header_metadata, preload = False),
    Component(DetectedMetadata, init = detect_metadata, preload = False),
    Component(MergedMetadata, init = merge_metadata, preload = False),
]
Exemplo n.º 20
0
        if resp.status != 200:
            logger.error('problem while posting slack message. %s', resp)
            return ''

        return resp_str

    async def dispatch_event(self, event={}):
        event_type = event['event']['type']
        team_id = event["team_id"]

        if event_type == 'message':
            logger.debug('Message!')
            m_text = event['event'].get('text', '').lower()

            if 'price' in m_text:
                logger.debug('Price Message matched!')
                user_id = event["event"]["user"]
                await self.send_price_message(team_id, user_id,
                                              event["event"]["channel"],
                                              m_text)

                logger.debug('Pricing Message sent!')
                return {'message': 'Pricing!'}

        message = "I do not have an event handler for the %s" % event_type
        return Response(message, 200, headers={"X-Slack-No-Retry": '1'})


components = [Component(CryptoBot, init=CryptoBot)]
Exemplo n.º 21
0
    """
    if not user:
        return {'message': 'tsu tsu'}
    return {'message': f'you are a true user {user.username}'}


def secret(user: User):
    """
    A secret url of the service, only available for admin.
    """
    if not user:
        return {'message': 'tsu tsu'}
    if not user.is_admin:
        return {'message': f'wont tell you ma secret {user.username}'}
    return {
        'message': f'you are a true user {user.username}',
        'secret': f'this is a super secret message',
    }


ROUTES = [
    Route('/service/protected', 'GET', protected),
    Route('/service/secret', 'GET', secret),
]

COMPONENTS = [
    Component(User, authenticate_user),
]

app = App(routes=ROUTES, components=COMPONENTS)
Exemplo n.º 22
0
    atomic.__exit__(exc_type, exc_value, exc_traceback)


def flush():  # pragma: nocover
    call_command('flush', '--no-input')


def makemigrations():  # pragma: nocover
    call_command('makemigrations')


def migrate():
    call_command('migrate')


def showmigrations():  # pragma: nocover
    call_command('showmigrations')


components = [
    Component(DjangoORM),
    Component(Session, init=get_session, preload=False)
]

commands = [
    Command('flush', flush),
    Command('makemigrations', makemigrations),
    Command('migrate', migrate),
    Command('showmigrations', showmigrations)
]