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']
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)
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']
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
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), ]
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)]
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)
# -*- 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()
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), ]
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), ]
@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), ]
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'],
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
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
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()
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) ]
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)
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), ]
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)]
""" 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)
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) ]