152 lines
3.8 KiB
Python
152 lines
3.8 KiB
Python
|
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
|
||
|
}
|