Пример #1
0
    def class_rebuilder(cls):   # decorator

        def init(self):
            logger.info("[%s] Applying ID to endopoint:%s of type '%s'"
                        % (self.__class__.__name__, name, idtype))
            self.set_method_id(name, idtype)
            # logger.debug("New init %s %s" % (name, idtype))
            super(cls, self).__init__()

        NewClass = Meta.metaclassing(
            cls, cls.__name__ + '_withid', {'__init__': init})
        return NewClass
Пример #2
0
        def decorated(*args, **kwargs):

            # Recover the auth object
            auth, token = self.get_auth_from_header()
            # Internal API 'self' reference
            decorated_self = Meta.get_self_reference_from_args(*args)

            # Handling OPTIONS forwarded to our application:
            # ignore headers and let go, avoid unwanted interactions with CORS
            if request.method != 'OPTIONS':
                if auth and auth.username:
                    # case of username and password
                    password = self.get_password_callback(auth.username)
                else:
                    # case for a header token
                    password = None
                # Check authentication
                token_fn = g._custom_auth.verify_token
                if not self.authenticate(token_fn, auth, password):
                    # Clear TCP receive buffer of any pending data
                    request.data
                    headers = {
                        HTTPAUTH_AUTH_HEADER: self.authenticate_header()}
                    # Mimic the response from a normal endpoint
                    # To use the same standards
                    return decorated_self.force_response(
                        errors={"Invalid token": "Received '%s'" % token},
                        headers=headers,
                        code=hcodes.HTTP_BAD_UNAUTHORIZED
                    )

            # Check roles
            if len(roles) > 0:
                roles_fn = g._custom_auth.verify_roles
                if not self.authenticate_roles(roles_fn, roles):
                    return decorated_self.force_response(
                        errors={"Missing privileges":
                                "One or more role required"},
                        code=hcodes.HTTP_BAD_UNAUTHORIZED
                    )

            return f(*args, **kwargs)
Пример #3
0
def create_app(name=__name__, debug=False,
               worker_mode=False, testing_mode=False,
               avoid_context=False, enable_security=True,
               skip_endpoint_mapping=False,
               **kwargs):
    """ Create the server istance for Flask application """

    #################################################
    # Flask app instance
    #################################################
    from .confs import config
    microservice = Flask(name, **kwargs)

    ##############################
    # @microservice.before_first_request
    # def first():
    #     print("BEFORE THE VERY FIRST REQUEST", g)

    # @microservice.before_request
    # def before():
    #     print("BEFORE EVERY REQUEST...")

    # @microservice.after_request
    # def after(response):
    #     print("AFTER EVERY REQUEST...")
    #     return response

    ##############################
    # Disable security if launching celery workers
    if worker_mode:
        enable_security = False

    # Set app internal testing mode if create_app received the parameter
    if testing_mode:
        microservice.config['TESTING'] = testing_mode
    ##############################
    # Flask configuration from config file
    microservice.config.from_object(config)

    if ENVVAR_DEBUG is not None:
        try:
            tmp = int(ENVVAR_DEBUG) == 1
        except:
            tmp = str(ENVVAR_DEBUG).lower() == 'true'
        debug = tmp  # bool(tmp)
    microservice.config['DEBUG'] = debug

    # Set the new level of debugging
    logger = get_logger(__name__, debug)
    logger.info("FLASKING! Created application")

    ##############################
    if PRODUCTION:

        logger.info("Production server ON")

## // TO FIX or CHECK
        # # Check and use a random file a secret key.
        # install_secret_key(microservice)

        # probably useless
        # # http://stackoverflow.com/a/26636880/2114395
        # microservice.config.update(
        #     dict(PREFERRED_URL_SCHEME = 'https')
        # )

        # # To enable exceptions printing inside uWSGI
        # # http://stackoverflow.com/a/17839750/2114395
        # from werkzeug.debug import DebuggedApplication
        # app.wsgi_app = DebuggedApplication(app.wsgi_app, True)

    #################################################
    # Other components
    #################################################

    ##############################
    # Cors
    from .cors import cors
    cors.init_app(microservice)
    logger.info("FLASKING! Injected CORS")

    ##############################
    # DATABASE/SERVICEs CHECKS
    from .resources.services.detect import services as internal_services
    for service, myclass in internal_services.items():
        logger.info("Available service %s" % service)
        myclass(check_connection=True, app=microservice)

    ##############################
    # Enabling our internal Flask customized response
    from .response import InternalResponse
    microservice.response_class = InternalResponse

    ##############################
    # Flask security
    if enable_security:

        # Dynamically load the authentication service
        meta = Meta()
        module_base = __package__ + ".resources.services.authentication"
        auth_service = os.environ.get('BACKEND_AUTH_SERVICE', '')
        module_name = module_base + '.' + auth_service
        logger.debug("Trying to load the module %s" % module_name)
        module = meta.get_module_from_string(module_name)

        init_auth = create_auth_instance(
            module, internal_services, microservice)

        # Global namespace inside the Flask server
        @microservice.before_request
        def enable_authentication_per_request():
            """ Save auth object """

            # Authentication the right (per-instance) way
            custom_auth = create_auth_instance(
                module, internal_services, microservice)

            # Save globally across the code
            g._custom_auth = custom_auth

        # OLD BAD
        # def enable_global_authentication():
        #     """ Save auth object """
        #     g._custom_auth = custom_auth

        # Enabling also OAUTH library
        from .oauth import oauth
        oauth.init_app(microservice)

        logger.info("FLASKING! Injected security internal module")

    if not worker_mode:
        # Global namespace inside the Flask server
        @microservice.before_request
        def enable_global_services():
            """ Save all databases/services """
            g._services = internal_services

    ##############################
    # Restful plugin
    if not skip_endpoint_mapping:
        from .rest import Api, EndpointsFarmer, create_endpoints
        # Defining AUTOMATIC Resources
        current_endpoints = \
            create_endpoints(EndpointsFarmer(Api), enable_security, debug)
        # Restful init of the app
        current_endpoints.rest_api.init_app(microservice)

    ##############################
    # Init objects inside the app context
    if not avoid_context:
        with microservice.app_context():

            # Set global objects for celery workers
            if worker_mode:
                from commons.globals import mem
                mem.services = internal_services

            # Note:
            # Databases are already initialized inside the instances farm
            # Outside of the context
            # p.s. search inside this file for 'myclass('

            # Init users/roles for Security
            if enable_security:
                # custom_auth.setup_secret(microservice.config['SECRET_KEY'])
                # custom_auth.init_users_and_roles()
                init_auth.init_users_and_roles()

            # Allow a custom method for mixed services init
            try:
                from .resources.custom import services as custom_services
                custom_services.init(internal_services, enable_security)
            except:
                logger.debug("No custom init available for mixed services")

    ##############################
    # Logging responses
    @microservice.after_request
    def log_response(response):

        data = handle_log_output(request.data)

        # Limit the parameters string size, sometimes it's too big
        for k in data:
            # print("K", k, "DATA", data)
            try:
                if not isinstance(data[k], str):
                    continue
                if len(data[k]) > MAX_CHAR_LEN:
                    data[k] = data[k][:MAX_CHAR_LEN] + "..."
            except IndexError:
                pass

        logger.info("{} {} {} {}".format(
                    request.method, request.url, data, response))
        return response

    ##############################
    # Enabling user callbacks after a request
    @microservice.after_request
    def call_after_request_callbacks(response):
        for callback in getattr(g, 'after_request_callbacks', ()):
            callback(response)
        return response

    ##############################
    # App is ready
    return microservice
Пример #4
0
"""

# from restapi.resources.services.celery.tasks import MyCelery
from commons.services.celery import celery_app
from restapi.server import create_app
from commons.meta import Meta
from commons.logs import get_logger

logger = get_logger(__name__)

################################################
# Reload Flask app code also for the worker
# This is necessary to have the app context available
app = create_app(worker_mode=True, debug=True)

# Recover celery app with current app
# celery_app = MyCelery(app)._current

# celery_app = MyCelery(app)._current
logger.debug("Celery %s" % celery_app)

################################################
# Import tasks modules to make sure all tasks are avaiable

meta = Meta()
main_package = "commons.tasks."
# Base tasks
submodules = meta.import_submodules_from_package(main_package + "base")
# Custom tasks
submodules = meta.import_submodules_from_package(main_package + "custom")
Пример #5
0
    def single_rest(self, config_file):

        meta = Meta()
        resources = []
        sections = {}

        if not os.path.exists(config_file):
            logger.warning("File '%s' does not exist! Skipping." % config_file)
            return resources

        #########################
        # Read the configuration inside this init file

        # JSON CASE
        try:
            sections = self.read_complex_config(config_file)
        except:  # json.commentjson.JSONLibraryException:
            logger.critical("Format error!\n" +
                            "'%s' file is not in JSON format" % config_file)
            exit(1)

        if 'apis' not in sections:
            logger.critical(
                "Section 'apis' not found in '%s' file" % config_file
            )
            exit(1)

        #########################
        # Use sections found
        for section, items in iteritems(sections['apis']):

            logger.debug("Configuration read: {Section: " + section + "}")

            module = meta.get_module_from_string(
                __package__ + '.resources.custom.' + section)
            # Skip what you cannot use
            if module is None:
                logger.warning("Could not find module '%s'..." % section)
                continue

            for classname, endpoints in iteritems(items):
                myclass = meta.get_class_from_string(classname, module)
                # Again skip
                if myclass is None:
                    continue
                else:
                    logger.debug("REST! Found resource: " +
                                 section + '.' + classname)

                # Get the best endpoint comparing inside against configuration
                instance = myclass()

                oldendpoint, endkey, endtype = instance.get_endpoint()
                if len(endpoints) < 1:
                    endpoints = [oldendpoint]

                endpoint_id = None
                if endkey is not None and endtype is not None:
                    endpoint_id = endtype + ':' + endkey

                resources.append((myclass, instance, endpoints, endpoint_id))

        return resources