Example #1
0
    def load_controllers(
        self,
        configurator: Configurator,
        app_config: CFG,
        route_prefix: str,
        context: PyramidContext,
    ) -> None:
        # TODO - G.M - 2019-03-18 - check if possible to avoid this import here,
        # import is here because import AgendaController without adding it to
        # pyramid make trouble in hapic which try to get view related
        # to controller but failed.
        from tracim_backend.applications.agenda.controllers.agenda_controller import (
            AgendaController,
        )
        from tracim_backend.applications.agenda.controllers.radicale_proxy_controller import (
            RadicaleProxyController,
        )

        configurator.include(add_www_authenticate_header_for_caldav)
        # caldav exception
        context.handle_exception(CaldavNotAuthorized, HTTPStatus.FORBIDDEN)
        context.handle_exception(CaldavNotAuthenticated, HTTPStatus.UNAUTHORIZED)
        # controller
        radicale_proxy_controller = RadicaleProxyController(
            proxy_base_address=app_config.CALDAV__RADICALE_PROXY__BASE_URL,
            radicale_base_path=app_config.CALDAV__RADICALE__BASE_PATH,
            radicale_user_path=app_config.CALDAV__RADICALE__USER_PATH,
            radicale_workspace_path=app_config.CALDAV_RADICALE_WORKSPACE_PATH,
        )
        agenda_controller = AgendaController()
        configurator.include(agenda_controller.bind, route_prefix=BASE_API)
        configurator.include(radicale_proxy_controller.bind)
    def test_func__catch_one_exception__ok__pyramid(self):
        from pyramid.config import Configurator

        configurator = Configurator(autocommit=True)
        context = PyramidContext(
            configurator,
            default_error_builder=MarshmallowDefaultErrorBuilder())
        hapic = Hapic(processor_class=MarshmallowProcessor)
        hapic.set_context(context)

        def my_view(context, request):
            raise ZeroDivisionError("An exception message")

        configurator.add_route("my_view", "/my-view", request_method="GET")
        configurator.add_view(my_view, route_name="my_view", renderer="json")

        # FIXME - G.M - 17-05-2018 - Verify if:
        # - other view that work/raise an other exception do not go
        # into this code for handle this exceptions.
        # - response come clearly from there, not from web framework:
        #  Check not only http code, but also body.
        # see  issue #158 (https://github.com/algoo/hapic/issues/158)
        context.handle_exception(ZeroDivisionError, http_code=400)

        app = configurator.make_wsgi_app()
        test_app = TestApp(app)
        response = test_app.get("/my-view", status="*")

        assert 400 == response.status_code
Example #3
0
def get_pyramid_context():
    from example.fake_api.pyramid_api import hapic as h

    configurator = Configurator(autocommit=True)
    controllers = PyramidController()
    controllers.bind(configurator)
    h.reset_context()
    h.set_context(
        PyramidContext(configurator,
                       default_error_builder=MarshmallowDefaultErrorBuilder()))
    pyramid_app = configurator.make_wsgi_app()
    return {"hapic": h, "app": pyramid_app}
Example #4
0
def get_pyramid_context():
    h = Hapic(processor_class=MarshmallowProcessor)

    configurator = Configurator(autocommit=True)

    h.reset_context()
    h.set_context(
        PyramidContext(configurator, default_error_builder=MarshmallowDefaultErrorBuilder())
    )

    class MySchema(marshmallow.Schema):
        name = marshmallow.fields.String(required=True)

    @h.with_api_doc()
    @h.input_body(MySchema())
    def my_controller():
        return {"name": "test"}

    configurator.add_route("test", "/test", request_method="POST")
    configurator.add_view(my_controller, route_name="test")
    pyramid_app = configurator.make_wsgi_app()
    return {"hapic": h, "app": pyramid_app}
Example #5
0
def web(global_config, **local_settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings = global_config
    settings.update(local_settings)
    # set CFG object
    app_config = CFG(settings)
    app_config.configure_filedepot()
    settings['CFG'] = app_config
    configurator = Configurator(settings=settings, autocommit=True)
    # Add AuthPolicy
    configurator.include("pyramid_beaker")
    configurator.include("pyramid_multiauth")
    policies = []
    if app_config.REMOTE_USER_HEADER:
        policies.append(
            RemoteAuthentificationPolicy(
                remote_user_email_login_header=app_config.REMOTE_USER_HEADER,
            ))
    policies.append(
        CookieSessionAuthentificationPolicy(
            reissue_time=app_config.SESSION_REISSUE_TIME),  # nopep8
    )
    if app_config.API_KEY:
        policies.append(
            ApiTokenAuthentificationPolicy(
                api_key_header=TRACIM_API_KEY_HEADER,
                api_user_email_login_header=TRACIM_API_USER_EMAIL_LOGIN_HEADER
            ), )
    policies.append(
        TracimBasicAuthAuthenticationPolicy(realm=BASIC_AUTH_WEBUI_REALM), )
    # Hack for ldap
    if AuthType.LDAP in app_config.AUTH_TYPES:
        import ldap3
        configurator.include('pyramid_ldap3')
        configurator.ldap_setup(app_config.LDAP_URL,
                                bind=app_config.LDAP_BIND_DN,
                                passwd=app_config.LDAP_BIND_PASS,
                                use_tls=app_config.LDAP_TLS,
                                use_pool=app_config.LDAP_USE_POOL,
                                pool_size=app_config.LDAP_POOL_SIZE,
                                pool_lifetime=app_config.LDAP_POOL_LIFETIME,
                                get_info=app_config.LDAP_GET_INFO)
        configurator.ldap_set_login_query(
            base_dn=app_config.LDAP_USER_BASE_DN,
            filter_tmpl=app_config.LDAP_USER_FILTER,
            scope=ldap3.LEVEL,
            attributes=ldap3.ALL_ATTRIBUTES)

    configurator.include(add_cors_support)
    # make sure to add this before other routes to intercept OPTIONS
    configurator.add_cors_preflight_handler()
    # Default authorization : Accept anything.
    configurator.set_authorization_policy(AcceptAllAuthorizationPolicy())
    authn_policy = MultiAuthenticationPolicy(policies)
    configurator.set_authentication_policy(authn_policy)
    # INFO - GM - 11-04-2018 - set default perm
    # setting default perm is needed to force authentification
    # mecanism in all views.
    configurator.set_default_permission(TRACIM_DEFAULT_PERM)
    # Override default request
    configurator.set_request_factory(TracimRequest)
    # Pyramids "plugin" include.
    configurator.include('pyramid_jinja2')
    # Add SqlAlchemy DB
    configurator.include('.models.setup_models')
    # set Hapic
    context = PyramidContext(
        configurator=configurator,
        default_error_builder=ErrorSchema(),
        debug=app_config.DEBUG,
    )
    hapic.set_context(context)
    # INFO - G.M - 2018-07-04 - global-context exceptions
    # Not found
    context.handle_exception(PageNotFound, HTTPStatus.NOT_FOUND)
    # Bad request
    context.handle_exception(WorkspaceNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(UserNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(ContentNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(WorkspaceNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(UserDoesNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentInNotEditableState, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotAllowed, HTTPStatus.BAD_REQUEST)
    context.handle_exception(InvalidId, HTTPStatus.BAD_REQUEST)
    context.handle_exception(SameValueError, HTTPStatus.BAD_REQUEST)
    # Auth exception
    context.handle_exception(NotAuthenticated, HTTPStatus.UNAUTHORIZED)
    context.handle_exception(UserAuthenticatedIsNotActive,
                             HTTPStatus.FORBIDDEN)
    context.handle_exception(AuthenticationFailed, HTTPStatus.FORBIDDEN)
    context.handle_exception(InsufficientUserRoleInWorkspace,
                             HTTPStatus.FORBIDDEN)  # nopep8
    context.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
    # Internal server error
    context.handle_exception(OperationalError,
                             HTTPStatus.INTERNAL_SERVER_ERROR)
    context.handle_exception(Exception, HTTPStatus.INTERNAL_SERVER_ERROR)

    # Add controllers
    session_controller = SessionController()
    system_controller = SystemController()
    user_controller = UserController()
    account_controller = AccountController()
    reset_password_controller = ResetPasswordController()
    workspace_controller = WorkspaceController()
    comment_controller = CommentController()
    html_document_controller = HTMLDocumentController()
    thread_controller = ThreadController()
    file_controller = FileController()
    folder_controller = FolderController()
    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(account_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(reset_password_controller.bind,
                         route_prefix=BASE_API_V2)  # nopep8
    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(comment_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(html_document_controller.bind,
                         route_prefix=BASE_API_V2)  # nopep8
    configurator.include(thread_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(file_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(folder_controller.bind, route_prefix=BASE_API_V2)
    if app_config.FRONTEND_SERVE:
        configurator.include('pyramid_mako')
        frontend_controller = FrontendController(
            app_config.FRONTEND_DIST_FOLDER_PATH)  # nopep8
        configurator.include(frontend_controller.bind)

    hapic.add_documentation_view(
        '/api/v2/doc',
        'Tracim v2 API',
        'API of Tracim v2',
    )
    return configurator.make_wsgi_app()
Example #6
0
def web(global_config, **local_settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings = deepcopy(global_config)
    settings.update(local_settings)
    # set CFG object
    app_config = CFG(settings)
    app_config.configure_filedepot()
    settings["CFG"] = app_config
    configurator = Configurator(settings=settings, autocommit=True)
    # Add beaker session cookie
    tracim_setting_for_beaker = sliced_dict(settings,
                                            beginning_key_string="session.")
    tracim_setting_for_beaker[
        "session.data_dir"] = app_config.SESSION__DATA_DIR
    tracim_setting_for_beaker[
        "session.lock_dir"] = app_config.SESSION__LOCK_DIR
    session_factory = pyramid_beaker.session_factory_from_settings(
        tracim_setting_for_beaker)
    configurator.set_session_factory(session_factory)
    pyramid_beaker.set_cache_regions_from_settings(tracim_setting_for_beaker)
    # Add AuthPolicy
    configurator.include("pyramid_multiauth")
    policies = []
    if app_config.REMOTE_USER_HEADER:
        policies.append(
            RemoteAuthentificationPolicy(
                remote_user_email_login_header=app_config.REMOTE_USER_HEADER))
    policies.append(
        CookieSessionAuthentificationPolicy(
            reissue_time=app_config.SESSION__REISSUE_TIME))
    if app_config.API__KEY:
        policies.append(
            ApiTokenAuthentificationPolicy(
                api_key_header=TRACIM_API_KEY_HEADER,
                api_user_email_login_header=TRACIM_API_USER_EMAIL_LOGIN_HEADER,
            ))
    policies.append(
        TracimBasicAuthAuthenticationPolicy(realm=BASIC_AUTH_WEBUI_REALM))
    # Hack for ldap
    if AuthType.LDAP in app_config.AUTH_TYPES:
        import ldap3

        configurator.include("pyramid_ldap3")
        configurator.ldap_setup(
            app_config.LDAP_URL,
            bind=app_config.LDAP_BIND_DN,
            passwd=app_config.LDAP_BIND_PASS,
            use_tls=app_config.LDAP_TLS,
            use_pool=app_config.LDAP_USE_POOL,
            pool_size=app_config.LDAP_POOL_SIZE,
            pool_lifetime=app_config.LDAP_POOL_LIFETIME,
            get_info=app_config.LDAP_GET_INFO,
        )
        configurator.ldap_set_login_query(
            base_dn=app_config.LDAP_USER_BASE_DN,
            filter_tmpl=app_config.LDAP_USER_FILTER,
            scope=ldap3.LEVEL,
            attributes=ldap3.ALL_ATTRIBUTES,
        )

    configurator.include(add_cors_support)
    # make sure to add this before other routes to intercept OPTIONS
    configurator.add_cors_preflight_handler()
    # Default authorization : Accept anything.
    configurator.set_authorization_policy(AcceptAllAuthorizationPolicy())
    authn_policy = MultiAuthenticationPolicy(policies)
    configurator.set_authentication_policy(authn_policy)
    # INFO - GM - 11-04-2018 - set default perm
    # setting default perm is needed to force authentification
    # mecanism in all views.
    configurator.set_default_permission(TRACIM_DEFAULT_PERM)
    # Override default request
    configurator.set_request_factory(TracimRequest)
    # Pyramids "plugin" include.
    configurator.include("pyramid_jinja2")
    # Add SqlAlchemy DB
    init_models(configurator, app_config)
    # set Hapic
    context = PyramidContext(configurator=configurator,
                             default_error_builder=ErrorSchema(),
                             debug=app_config.DEBUG)
    hapic.set_context(context)
    # INFO - G.M - 2018-07-04 - global-context exceptions
    # Not found
    context.handle_exception(PageNotFound, HTTPStatus.NOT_FOUND)
    # Bad request
    context.handle_exception(WorkspaceNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)
    context.handle_exception(UserNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)
    context.handle_exception(WorkspaceNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(UserDoesNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentInNotEditableState, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotAllowed, HTTPStatus.BAD_REQUEST)
    context.handle_exception(InvalidId, HTTPStatus.BAD_REQUEST)
    context.handle_exception(SameValueError, HTTPStatus.BAD_REQUEST)
    # Auth exception
    context.handle_exception(NotAuthenticated, HTTPStatus.UNAUTHORIZED)
    context.handle_exception(UserGivenIsNotTheSameAsAuthenticated,
                             HTTPStatus.FORBIDDEN)
    context.handle_exception(UserAuthenticatedIsNotActive,
                             HTTPStatus.FORBIDDEN)
    context.handle_exception(AuthenticationFailed, HTTPStatus.FORBIDDEN)
    context.handle_exception(InsufficientUserRoleInWorkspace,
                             HTTPStatus.FORBIDDEN)
    context.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
    # Internal server error
    context.handle_exception(OperationalError,
                             HTTPStatus.INTERNAL_SERVER_ERROR)
    context.handle_exception(Exception, HTTPStatus.INTERNAL_SERVER_ERROR)

    # Add controllers
    session_controller = SessionController()
    system_controller = SystemController()
    user_controller = UserController()
    account_controller = AccountController()
    reset_password_controller = ResetPasswordController()
    workspace_controller = WorkspaceController()
    comment_controller = CommentController()
    html_document_controller = HTMLDocumentController()
    thread_controller = ThreadController()
    file_controller = FileController()
    folder_controller = FolderController()
    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(account_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(reset_password_controller.bind,
                         route_prefix=BASE_API_V2)
    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(comment_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(html_document_controller.bind,
                         route_prefix=BASE_API_V2)
    configurator.include(thread_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(file_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(folder_controller.bind, route_prefix=BASE_API_V2)
    if app_config.CALDAV__ENABLED:
        # TODO - G.M - 2019-03-18 - check if possible to avoid this import here,
        # import is here because import AgendaController without adding it to
        # pyramid make trouble in hapic which try to get view related
        # to controller but failed.
        from tracim_backend.views.agenda_api.agenda_controller import AgendaController

        configurator.include(add_www_authenticate_header_for_caldav)
        # caldav exception
        context.handle_exception(CaldavNotAuthorized, HTTPStatus.FORBIDDEN)
        context.handle_exception(CaldavNotAuthenticated,
                                 HTTPStatus.UNAUTHORIZED)
        # controller
        radicale_proxy_controller = RadicaleProxyController(
            proxy_base_address=app_config.CALDAV__RADICALE_PROXY__BASE_URL,
            radicale_base_path=app_config.CALDAV__RADICALE__BASE_PATH,
            radicale_user_path=app_config.CALDAV__RADICALE__USER_PATH,
            radicale_workspace_path=app_config.CALDAV_RADICALE_WORKSPACE_PATH,
        )
        agenda_controller = AgendaController()
        configurator.include(agenda_controller.bind, route_prefix=BASE_API_V2)
        configurator.include(radicale_proxy_controller.bind)

    # TODO - G.M - 2019-05-17 - check if possible to avoid this import here,
    # import is here because import SearchController without adding it to
    # pyramid make trouble in hapic which try to get view related
    # to controller but failed.
    from tracim_backend.lib.search.search_factory import SearchFactory

    search_controller = SearchFactory.get_search_controller(app_config)

    configurator.include(search_controller.bind, route_prefix=BASE_API_V2)
    if app_config.FRONTEND__SERVE:
        configurator.include("pyramid_mako")
        frontend_controller = FrontendController(
            app_config.FRONTEND__DIST_FOLDER_PATH)
        configurator.include(frontend_controller.bind)

    hapic.add_documentation_view("/api/v2/doc", "Tracim v2 API",
                                 "API of Tracim v2")
    return configurator.make_wsgi_app()
Example #7
0
def web(global_config, **local_settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings = global_config
    settings.update(local_settings)
    # set CFG object
    app_config = CFG(settings)
    app_config.configure_filedepot()
    settings['CFG'] = app_config
    configurator = Configurator(settings=settings, autocommit=True)
    # Add BasicAuthPolicy
    authn_policy = BasicAuthAuthenticationPolicy(
        basic_auth_check_credentials,
        realm=BASIC_AUTH_WEBUI_REALM,
    )
    configurator.include(add_cors_support)
    # make sure to add this before other routes to intercept OPTIONS
    configurator.add_cors_preflight_handler()
    # Default authorization : Accept anything.
    configurator.set_authorization_policy(AcceptAllAuthorizationPolicy())
    configurator.set_authentication_policy(authn_policy)
    # INFO - GM - 11-04-2018 - set default perm
    # setting default perm is needed to force authentification
    # mecanism in all views.
    configurator.set_default_permission(TRACIM_DEFAULT_PERM)
    # Override default request
    configurator.set_request_factory(TracimRequest)
    # Pyramids "plugin" include.
    configurator.include('pyramid_jinja2')
    # Add SqlAlchemy DB
    configurator.include('.models')
    # set Hapic
    context = PyramidContext(
        configurator=configurator,
        default_error_builder=ErrorSchema(),
        debug=app_config.DEBUG,
    )
    hapic.set_context(context)
    # INFO - G.M - 2018-07-04 - global-context exceptions
    # Not found
    context.handle_exception(NotFound, HTTPStatus.NOT_FOUND)
    # Bad request
    context.handle_exception(WorkspaceNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(UserNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(ContentNotFoundInTracimRequest,
                             HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(WorkspaceNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(UserDoesNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotAllowed, HTTPStatus.BAD_REQUEST)
    context.handle_exception(InvalidId, HTTPStatus.BAD_REQUEST)
    # Auth exception
    context.handle_exception(NotAuthenticated, HTTPStatus.UNAUTHORIZED)
    context.handle_exception(UserNotActive, HTTPStatus.FORBIDDEN)
    context.handle_exception(AuthenticationFailed, HTTPStatus.FORBIDDEN)
    context.handle_exception(InsufficientUserRoleInWorkspace,
                             HTTPStatus.FORBIDDEN)  # nopep8
    context.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
    # Internal server error
    context.handle_exception(OperationalError,
                             HTTPStatus.INTERNAL_SERVER_ERROR)
    context.handle_exception(Exception, HTTPStatus.INTERNAL_SERVER_ERROR)

    # Add controllers
    session_controller = SessionController()
    system_controller = SystemController()
    user_controller = UserController()
    workspace_controller = WorkspaceController()
    comment_controller = CommentController()
    html_document_controller = HTMLDocumentController()
    thread_controller = ThreadController()
    file_controller = FileController()
    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(comment_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(html_document_controller.bind,
                         route_prefix=BASE_API_V2)  # nopep8
    configurator.include(thread_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(file_controller.bind, route_prefix=BASE_API_V2)

    hapic.add_documentation_view(
        '/api/v2/doc',
        'Tracim v2 API',
        'API of Tracim v2',
    )
    return configurator.make_wsgi_app()
Example #8
0
def web(global_config, **local_settings):
    """ This function returns a Pyramid WSGI application.
    """
    settings = global_config
    settings.update(local_settings)
    # set CFG object
    app_config = CFG(settings)
    app_config.configure_filedepot()
    settings['CFG'] = app_config
    configurator = Configurator(settings=settings, autocommit=True)
    # Add AuthPolicy
    configurator.include("pyramid_beaker")
    configurator.include("pyramid_multiauth")
    policies = []
    if app_config.REMOTE_USER_HEADER:
        policies.append(
            RemoteAuthentificationPolicy(
                remote_user_email_login_header=app_config.REMOTE_USER_HEADER,
            )
        )
    policies.append(
        CookieSessionAuthentificationPolicy(
            reissue_time=app_config.SESSION_REISSUE_TIME),  # nopep8
    )
    if app_config.API_KEY:
        policies.append(
            ApiTokenAuthentificationPolicy(
                api_key_header=TRACIM_API_KEY_HEADER,
                api_user_email_login_header=TRACIM_API_USER_EMAIL_LOGIN_HEADER
            ),
        )
    policies.append(
        TracimBasicAuthAuthenticationPolicy(
            realm=BASIC_AUTH_WEBUI_REALM
        ),
    )
    # Hack for ldap
    if AuthType.LDAP in app_config.AUTH_TYPES:
        import ldap3
        configurator.include('pyramid_ldap3')
        configurator.ldap_setup(
            app_config.LDAP_URL,
            bind=app_config.LDAP_BIND_DN,
            passwd=app_config.LDAP_BIND_PASS,
            use_tls=app_config.LDAP_TLS,
            use_pool=app_config.LDAP_USE_POOL,
            pool_size=app_config.LDAP_POOL_SIZE,
            pool_lifetime=app_config.LDAP_POOL_LIFETIME,
            get_info=app_config.LDAP_GET_INFO
        )
        configurator.ldap_set_login_query(
            base_dn=app_config.LDAP_USER_BASE_DN,
            filter_tmpl=app_config.LDAP_USER_FILTER,
            scope=ldap3.LEVEL,
            attributes=ldap3.ALL_ATTRIBUTES
        )

    configurator.include(add_cors_support)
    # make sure to add this before other routes to intercept OPTIONS
    configurator.add_cors_preflight_handler()
    # Default authorization : Accept anything.
    configurator.set_authorization_policy(AcceptAllAuthorizationPolicy())
    authn_policy = MultiAuthenticationPolicy(policies)
    configurator.set_authentication_policy(authn_policy)
    # INFO - GM - 11-04-2018 - set default perm
    # setting default perm is needed to force authentification
    # mecanism in all views.
    configurator.set_default_permission(TRACIM_DEFAULT_PERM)
    # Override default request
    configurator.set_request_factory(TracimRequest)
    # Pyramids "plugin" include.
    configurator.include('pyramid_jinja2')
    # Add SqlAlchemy DB
    configurator.include('.models.setup_models')
    # set Hapic
    context = PyramidContext(
        configurator=configurator,
        default_error_builder=ErrorSchema(),
        debug=app_config.DEBUG,
    )
    hapic.set_context(context)
    # INFO - G.M - 2018-07-04 - global-context exceptions
    # Not found
    context.handle_exception(PageNotFound, HTTPStatus.NOT_FOUND)
    # Bad request
    context.handle_exception(WorkspaceNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(UserNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(ContentNotFoundInTracimRequest, HTTPStatus.BAD_REQUEST)  # nopep8
    context.handle_exception(WorkspaceNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(UserDoesNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentNotFound, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotExist, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentInNotEditableState, HTTPStatus.BAD_REQUEST)
    context.handle_exception(ContentTypeNotAllowed, HTTPStatus.BAD_REQUEST)
    context.handle_exception(InvalidId, HTTPStatus.BAD_REQUEST)
    context.handle_exception(SameValueError, HTTPStatus.BAD_REQUEST)
    # Auth exception
    context.handle_exception(NotAuthenticated, HTTPStatus.UNAUTHORIZED)
    context.handle_exception(UserAuthenticatedIsNotActive, HTTPStatus.FORBIDDEN)
    context.handle_exception(AuthenticationFailed, HTTPStatus.FORBIDDEN)
    context.handle_exception(InsufficientUserRoleInWorkspace, HTTPStatus.FORBIDDEN)  # nopep8
    context.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
    # Internal server error
    context.handle_exception(OperationalError, HTTPStatus.INTERNAL_SERVER_ERROR)
    context.handle_exception(Exception, HTTPStatus.INTERNAL_SERVER_ERROR)

    # Add controllers
    session_controller = SessionController()
    system_controller = SystemController()
    user_controller = UserController()
    account_controller = AccountController()
    reset_password_controller = ResetPasswordController()
    workspace_controller = WorkspaceController()
    comment_controller = CommentController()
    html_document_controller = HTMLDocumentController()
    thread_controller = ThreadController()
    file_controller = FileController()
    folder_controller = FolderController()
    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(account_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(reset_password_controller.bind, route_prefix=BASE_API_V2)  # nopep8
    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(comment_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(html_document_controller.bind, route_prefix=BASE_API_V2)  # nopep8
    configurator.include(thread_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(file_controller.bind, route_prefix=BASE_API_V2)
    configurator.include(folder_controller.bind, route_prefix=BASE_API_V2)
    if app_config.FRONTEND_SERVE:
        configurator.include('pyramid_mako')
        frontend_controller = FrontendController(app_config.FRONTEND_DIST_FOLDER_PATH)  # nopep8
        configurator.include(frontend_controller.bind)

    hapic.add_documentation_view(
        '/api/v2/doc',
        'Tracim v2 API',
        'API of Tracim v2',
    )
    return configurator.make_wsgi_app()
        configurator.add_view(self.get_user_avatar,
                              route_name="get_user_avatar")

        configurator.add_route("update_user_avatar",
                               "/users/{id}/avatar",
                               request_method="PUT")  # nopep8
        configurator.add_view(self.update_user_avatar,
                              route_name="update_user_avatar")


if __name__ == "__main__":
    configurator = Configurator(autocommit=True)
    controllers = PyramidController()
    controllers.bind(configurator)
    hapic.set_context(
        PyramidContext(configurator,
                       default_error_builder=SerpycoDefaultErrorBuilder()))

    print("")
    print("")
    print("GENERATING OPENAPI DOCUMENTATION")

    doc_title = "Demo API documentation"
    doc_description = ("This documentation has been generated from "
                       "code. You can see it using swagger: "
                       "http://editor2.swagger.io/")
    hapic.add_documentation_view("/doc/", doc_title, doc_description)
    openapi_file_name = "api-documentation.json"
    with open(openapi_file_name, "w") as openapi_file_handle:
        openapi_file_handle.write(
            json.dumps(
                hapic.generate_doc(title=doc_title,
        configurator.add_view(self.get_user_avatar,
                              route_name="get_user_avatar")

        configurator.add_route("update_user_avatar",
                               "/users/{id}/avatar",
                               request_method="PUT")  # nopep8
        configurator.add_view(self.update_user_avatar,
                              route_name="update_user_avatar")


if __name__ == "__main__":
    configurator = Configurator(autocommit=True)
    controllers = PyramidController()
    controllers.bind(configurator)
    hapic.set_context(
        PyramidContext(configurator,
                       default_error_builder=MarshmallowDefaultErrorBuilder()))

    print("")
    print("")
    print("GENERATING OPENAPI DOCUMENTATION")

    doc_title = "Demo API documentation"
    doc_description = ("This documentation has been generated from "
                       "code. You can see it using swagger: "
                       "http://editor2.swagger.io/")
    hapic.add_documentation_view("/doc/", doc_title, doc_description)
    openapi_file_name = "api-documentation.json"
    with open(openapi_file_name, "w") as openapi_file_handle:
        openapi_file_handle.write(
            json.dumps(
                hapic.generate_doc(title=doc_title,