Source code for portal_web

# For copyright and license terms, see COPYRIGHT.rst (top level of repository)
# Repository: https://github.com/C3S/portal_web

"""
Main module for the pyramid app.
"""

import os
import logging
from logging.config import fileConfig

from pyramid.config import Configurator
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
from pyramid_beaker import session_factory_from_settings

from .config import (
    replace_environment_vars,
    get_plugins,
    notfound
)
from .models import (
    Tdb,
    WebUser
)
from .resources import (
    WebRootFactory,
    ApiRootFactory
)

log = logging.getLogger(__name__)


[docs] def main(global_config, **settings): """ Configures and creates the app. Handles configuration of - debugpy debugging - app config - tryton database - session - policies - subscribers - route predicates - view predicates - request methods - translation directories - logging - root factories - resources - registry - views Contains the main logic of the plugin system by including settings, translation directories, logging configuration, views, ressources and registry information of the plugins in a well defined order. Args: global_config (dict): Parsed [DEFAULT] section of .ini file. **settings (dict): Parsed [app:main] section of .ini file. Returns: obj: a Pyramid WSGI application. """ # get environment environment = os.environ.get('ENVIRONMENT') # get plugin configuration plugins = get_plugins(settings) # update portal settings with plugin settings and replace environment vars for priority in sorted(plugins, reverse=True): settings.update(plugins[priority]['settings']) settings = replace_environment_vars(settings) # init app config config = Configurator(settings=settings) # configure tryton database Tdb._db = settings['tryton.database'] Tdb._company = settings['tryton.company'] Tdb._user = settings['tryton.user'] Tdb._configfile = settings['tryton.configfile'] Tdb.init() # configure session config.set_session_factory(factory=session_factory_from_settings(settings)) # configure policies config.set_authorization_policy(policy=ACLAuthorizationPolicy()) config.set_authentication_policy( policy=AuthTktAuthenticationPolicy( secret=settings['authentication.secret'], hashalg='sha512', callback=WebUser.groupfinder)) config.set_default_permission('administrator') # configure subscribers config.add_subscriber( subscriber='.config.add_templates', iface='pyramid.events.BeforeRender') config.add_subscriber( subscriber='.config.add_helpers', iface='pyramid.events.BeforeRender') config.add_subscriber( subscriber='.config.add_locale', iface='pyramid.events.NewRequest') config.add_subscriber( subscriber='.config.start_db_transaction', iface='pyramid.events.BeforeTraversal') config.add_subscriber( subscriber='.config.context_found', iface='pyramid.events.ContextFound') config.add_subscriber( subscriber='.config.stop_db_transaction', iface='pyramid.events.NewRequest') if settings['env'] in ['development', 'staging']: config.add_subscriber( subscriber='.config.debug_request', iface='pyramid.events.NewRequest') config.add_subscriber( subscriber='.config.debug_context', iface='pyramid.events.ContextFound') config.add_subscriber( subscriber='.config.debug_response', iface='pyramid.events.NewResponse') # configure predicates config.add_route_predicate( name='environment', factory='.config.Environment') config.add_view_predicate( name='environment', factory='.config.Environment') # configure request methods config.add_request_method( callable='.config.web_user', name='web_user', reify=True) config.add_request_method( callable='.config.party', name='party', reify=True) config.add_request_method( callable='.config.user', name='user', reify=True) config.add_request_method( callable='.config.roles', name='roles', reify=True) # configure translation directories for portal and plugins config.add_translation_dirs( 'colander:locale/', 'deform:locale/', 'portal_web:locale/') for priority in sorted(plugins): translation_dir = os.path.join( plugins[priority]['path'], plugins[priority]['name'], 'locale') if os.path.isdir(translation_dir): config.add_translation_dirs(translation_dir) # configure logging for portal and plugins for priority in sorted(plugins): fileConfig( plugins[priority]['path'] + '/' + environment + '.ini', disable_existing_loggers=False) # commit config with basic settings config.commit() # not found view (404 Error) config.add_notfound_view(notfound) # configure mailer if int(settings['mail.to_real_world']): config.include('pyramid_mailer') else: config.include('pyramid_mailer.testing') # enable debugpy debugging (open port 52000 for portal and 52001 for api!) if int(settings['debugger.debugpy']): debugging_port = False if settings['service'] == 'webgui': debugging_port = 52000 if settings['service'] == 'webapi': debugging_port = 52001 if debugging_port: log.debug(settings['service'] + " debugger listening to port " + str(debugging_port)) try: import debugpy # unconditional import breaks test coverage debugpy.listen(("0.0.0.0", debugging_port)) except Exception as ex: if hasattr(ex, 'message'): log.debug(ex.message) else: log.debug('debugpy debugging not possible: ' + ex.message) # configure webfrontend for portal and plugins if settings['service'] == 'webgui': # web root factory config.set_root_factory(factory=WebRootFactory) # web resources config.include('.includes.web_resources') for priority in sorted(plugins): config.include(plugins[priority]['name']+'.includes.web_resources') # web registry config.include('.includes.web_registry') for priority in sorted(plugins): config.include(plugins[priority]['name']+'.includes.web_registry') # web views for priority in sorted(plugins, reverse=True): config.include(plugins[priority]['name'] + '.includes.web_views') config.include('.includes.web_views') # api views if settings['api.in_web'] == 'true': config.include('cornice') for priority in sorted(plugins, reverse=True): config.include( plugins[priority]['name'] + '.includes.api_views', route_prefix=settings['api.in_web_path']) config.include( '.includes.api_views', route_prefix=settings['api.in_web_path']) # configure api for portal and plugins if settings['service'] == 'webapi': config.include('cornice') config.include('cornice_swagger') # api root factory config.set_root_factory(factory=ApiRootFactory) # api views for priority in sorted(plugins, reverse=True): config.include(plugins[priority]['name'] + '.includes.api_views') config.include('.includes.api_views') return config.make_wsgi_app()