import logging from config_app import app from config_app.util.config import config_provider from flask import Blueprint, request, session from flask_restful import Resource, abort, Api, reqparse from flask_restful.utils.cors import crossdomain from functools import partial, wraps logger = logging.getLogger(__name__) api_bp = Blueprint('api', __name__) CROSS_DOMAIN_HEADERS = ['Authorization', 'Content-Type', 'X-Requested-With'] class ApiExceptionHandlingApi(Api): @crossdomain(origin='*', headers=CROSS_DOMAIN_HEADERS) def handle_error(self, error): print('HANDLING ERROR IN API') return super(ApiExceptionHandlingApi, self).handle_error(error) api = ApiExceptionHandlingApi() class HelloWorld(Resource): def get(self): print("hit the dummy endpoint") return {'hello': 'world'} api.add_resource(HelloWorld, '/') def verify_not_prod(func): @add_method_metadata('enterprise_only', True) def wrapped(*args, **kwargs): # Verify that we are not running on a production (i.e. hosted) stack. If so, we fail. # This should never happen (because of the feature-flag on SUPER_USERS), but we want to be # absolutely sure. # if app.config['SERVER_HOSTNAME'].find('quay.io') >= 0: # TODO(config_port) fixme if False: logger.error('!!! Super user method called IN PRODUCTION !!!') raise StandardError() return func(*args, **kwargs) return wrapped def resource(*urls, **kwargs): def wrapper(api_resource): if not api_resource: return None api_resource.registered = True api.add_resource(api_resource, *urls, **kwargs) return api_resource return wrapper class ApiResource(Resource): registered = False method_decorators = [] def options(self): return None, 200 def add_method_metadata(name, value): def modifier(func): if func is None: return None if '__api_metadata' not in dir(func): func.__api_metadata = {} func.__api_metadata[name] = value return func return modifier def method_metadata(func, name): if func is None: return None if '__api_metadata' in dir(func): return func.__api_metadata.get(name, None) return None def no_cache(f): @wraps(f) def add_no_cache(*args, **kwargs): response = f(*args, **kwargs) if response is not None: response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' return response return add_no_cache nickname = partial(add_method_metadata, 'nickname') api.init_app(api_bp) # api.decorators = [csrf_protect(), # crossdomain(origin='*', headers=CROSS_DOMAIN_HEADERS), # process_oauth, time_decorator(api_bp.name, metric_queue), # require_xhr_from_browser] @resource('/v1/superuser/config') class SuperUserConfig(ApiResource): """ Resource for fetching and updating the current configuration, if any. """ schemas = { 'UpdateConfig': { 'type': 'object', 'description': 'Updates the YAML config file', 'required': [ 'config', 'hostname' ], 'properties': { 'config': { 'type': 'object' }, 'hostname': { 'type': 'string' }, 'password': { 'type': 'string' }, }, }, } @verify_not_prod @nickname('scGetConfig') def get(self): """ Returns the currently defined configuration, if any. """ config_object = config_provider.get_config() return { 'config': config_object }