def execute_created_user_actions(self, user: User) -> None: """ WARNING! This method will be deprecated soon, see https://github.com/tracim/tracim/issues/1589 and https://github.com/tracim/tracim/issues/1487 This method do post-create user actions """ # FIXME - G.M - 2019-03-18 - move this code to another place when # event mechanism is ready, see https://github.com/tracim/tracim/issues/1487 # event on_created_user should start hook use by agenda app code. app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(AGENDA__APP_SLUG): agenda_api = AgendaApi(current_user=self._user, session=self._session, config=self._config) try: agenda_already_exist = agenda_api.ensure_user_agenda_exists( user) if agenda_already_exist: logger.warning( self, "user {} has just been created but their own agenda already exists" .format(user.user_id), ) except AgendaServerConnectionError as exc: logger.error(self, "Cannot connect to the agenda server") logger.exception(self, exc) except Exception as exc: logger.error( self, "Something went wrong during agenda create/update") logger.exception(self, exc)
def execute_updated_user_actions(self, user: User) -> None: """ WARNING! This method will be deprecated soon, see https://github.com/tracim/tracim/issues/1589 and https://github.com/tracim/tracim/issues/1487 This method does post-update user actions """ # TODO - G.M - 04-04-2018 - [auth] # Check if this is already needed with # new auth system user.ensure_auth_token( validity_seconds=self._config.USER__AUTH_TOKEN__VALIDITY) # FIXME - G.M - 2019-03-18 - move this code to another place when # event mechanism is ready, see https://github.com/tracim/tracim/issues/1487 # event on_updated_user should start hook use by agenda app code. app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(AGENDA__APP_SLUG): agenda_api = AgendaApi(current_user=self._user, session=self._session, config=self._config) try: agenda_api.ensure_user_agenda_exists(user) except AgendaServerConnectionError as exc: logger.error(self, "Cannot connect to agenda server") logger.exception(self, exc) except Exception as exc: logger.error( self, "Something goes wrong during agenda create/update") logger.exception(self, exc)
def index(self, context, request: TracimRequest): app_config = request.registry.settings['CFG'] # TODO - G.M - 2018-08-07 - Refactor autogen valid app list for frontend frontend_apps = [] app_api = ApplicationApi( app_list=app_list, ) applications = app_api.get_all() for app in applications: app_frontend_path = APP_FRONTEND_PATH.replace('{minislug}', app.minislug) # nopep8 app_path = os.path.join(self.dist_folder_path, app_frontend_path) # nopep8 if os.path.exists(app_path): frontend_apps.append(app) return render_to_response( self._get_index_file_path(), { 'colors': { 'primary': ExtendedColor(app_config.APPS_COLORS['primary']), }, 'applications': frontend_apps, } )
def index(self, context, request: TracimRequest): app_config = request.registry.settings["CFG"] # type: CFG # TODO - G.M - 2018-08-07 - Refactor autogen valid app list for frontend frontend_apps = [] app_api = ApplicationApi(app_list=app_list) applications = [ app_api.get_application_in_context(app, app_config) for app in app_api.get_all() ] for app in applications: app_frontend_path = APP_FRONTEND_PATH.replace( "{minislug}", app.minislug) app_path = os.path.join(self.dist_folder_path, app_frontend_path) if os.path.exists(app_path): frontend_apps.append(app) return render_to_response( self._get_index_file_path(), { "colors": { "primary": ExtendedColor(app_config.APPS_COLORS["primary"]) }, "applications": frontend_apps, "website_title": app_config.WEBSITE__TITLE, "custom_toolbox_files": self.custom_toolbox_files, "cache_token": self.cache_token, "excluded_notifications": app_config.WEB__NOTIFICATIONS__EXCLUDED, }, )
def __init__(self, settings: typing.Dict[str, typing.Any]): # INFO - G.M - 2019-12-02 - Store own settings original dict, with copy # to avoid issue when serializing CFG object. settings dict is completed # with object in some context self.settings = settings.copy() self.config_info = [] # type: typing.List[ConfigParam] logger.debug(self, "CONFIG_PROCESS:1: load enabled apps") self.load_enabled_apps() logger.debug(self, "CONFIG_PROCESS:3: load config from settings") self.load_config() logger.debug(self, "CONFIG_PROCESS:4: check validity of config given") self._check_consistency() self.check_config_validity() logger.debug(self, "CONFIG_PROCESS:5: End of config process") app_lib = ApplicationApi(app_list=app_list, show_inactive=True) for app in app_lib.get_all(): logger.info( self, "LOADED_APP:{state}:{slug}:{label}".format( state="ENABLED" if app.is_active else "DISABLED", slug=app.slug, label=app.label, ), )
def applications(self, context, request: TracimRequest, hapic_data=None): """ Get list of alls applications installed in this tracim instance. """ app_config = request.registry.settings['CFG'] app_api = ApplicationApi(app_list=app_list, ) return app_api.get_all()
def test_api__get_applications__ok_200__nominal_case(self): """ Get applications list with a registered user. """ self.testapp.authorization = ( 'Basic', ( '*****@*****.**', '*****@*****.**' ) ) res = self.testapp.get('/api/v2/system/applications', status=200) res = res.json_body dbsession = get_tm_session(self.session_factory, transaction.manager) app_api = ApplicationApi( app_list=app_list, ) applications = app_api.get_all() assert len(res) == len(applications) for counter, application in enumerate(applications): assert res[counter]['label'] == application.label assert res[counter]['slug'] == application.slug assert res[counter]['fa_icon'] == application.fa_icon assert res[counter]['hexcolor'] == application.hexcolor assert res[counter]['is_active'] == application.is_active assert res[counter]['config'] == application.config
def get_config(self) -> ConfigModel: collaborative_document_edition_config = None app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(COLLABORATIVE_DOCUMENT_EDITION__APP_SLUG): from tracim_backend.applications.collaborative_document_edition.factory import ( CollaborativeDocumentEditionFactory, ) collaborative_document_edition_api = CollaborativeDocumentEditionFactory().get_lib( session=None, current_user=None, config=self._config ) collaborative_document_edition_config = collaborative_document_edition_api.get_config() return ConfigModel( email_notification_activated=self._config.EMAIL__NOTIFICATION__ACTIVATED, new_user_invitation_do_notify=self._config.NEW_USER__INVITATION__DO_NOTIFY, webdav_enabled=self._config.WEBDAV__UI__ENABLED, webdav_url=urljoin(self._config.WEBDAV__BASE_URL, self._config.WEBDAV__ROOT_PATH), collaborative_document_edition=collaborative_document_edition_config, content_length_file_size_limit=self._config.LIMITATION__CONTENT_LENGTH_FILE_SIZE, workspace_size_limit=self._config.LIMITATION__WORKSPACE_SIZE, workspaces_number_per_user_limit=self._config.LIMITATION__SHAREDSPACE_PER_USER, instance_name=self._config.WEBSITE__TITLE, email_required=self._config.EMAIL__REQUIRED, )
def execute_update_workspace_actions(self, workspace: Workspace) -> None: """ WARNING ! This method Will be Deprecated soon, see https://github.com/tracim/tracim/issues/1589 and https://github.com/tracim/tracim/issues/1487 This method do post update workspace actions """ # FIXME - G.M - 2019-03-18 - move this code to another place when # event mechanism is ready, see https://github.com/tracim/tracim/issues/1487 # event on_updated_workspace should start hook use by agenda app code. app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(AGENDA__APP_SLUG): # TODO - G.M - 2019-04-11 - Circular Import, will probably be remove # with event refactor, see https://github.com/tracim/tracim/issues/1487 from tracim_backend.applications.agenda.lib import AgendaApi if workspace.agenda_enabled: agenda_api = AgendaApi(current_user=self._user, session=self._session, config=self._config) try: agenda_api.ensure_workspace_agenda_exists(workspace) except AgendaServerConnectionError as exc: logger.error(self, "Cannot connect to agenda server") logger.exception(self, exc) except Exception as exc: logger.error( self, "Something goes wrong during agenda create/update") logger.exception(self, exc)
def hexcolor(self) -> str: if self.content_type.app: app_api = ApplicationApi(app_list) return app_api.get_application_in_context( self.content_type.app, self.app_config ).hexcolor return ""
def test_get_default_workspace_menu_entry__ok__agenda_disabled_workspace_case( self): app_config = Mock() app_config.APPS_COLORS = {} app_config.APPS_COLORS["primary"] = "#fff" agenda = DummyApp( label="Agenda", slug="agenda", fa_icon="calendar", config={}, main_route="/ui/workspaces/{workspace_id}/agenda", ) agenda.is_active = True app_api = ApplicationApi(app_list=[agenda], show_inactive=False) workspace = Mock() workspace.workspace_id = 12 workspace.agenda_enabled = False default_workspace_menu_entry = app_api.get_default_workspace_menu_entry( workspace=workspace, app_config=app_config) assert len(default_workspace_menu_entry) == 2 assert default_workspace_menu_entry[ 0].label == dashboard_menu_entry.label assert default_workspace_menu_entry[ 1].label == all_content_menu_entry.label
def index(self, context, request: TracimRequest): app_config = request.registry.settings["CFG"] # type: CFG # TODO - G.M - 2018-08-07 - Refactor autogen valid app list for frontend frontend_apps = [] app_api = ApplicationApi(app_list=app_list) applications = [ app_api.get_application_in_context(app, app_config) for app in app_api.get_all() ] for app in applications: app_frontend_path = APP_FRONTEND_PATH.replace( "{minislug}", app.minislug) app_path = os.path.join(self.dist_folder_path, app_frontend_path) if os.path.exists(app_path): frontend_apps.append(app) base_response = None csp_nonce = "" if app_config.CONTENT_SECURITY_POLICY__ENABLED: csp_nonce = os.urandom(CSP_NONCE_SIZE).hex() csp_headers = [] csp_header_key = ("Content-Security-Policy-Report-Only" if app_config.CONTENT_SECURITY_POLICY__REPORT_ONLY else "Content-Security-Policy") csp = "; ".join("{} {}".format(k, v) for k, v in BASE_CSP_DIRECTIVES) csp = "{}; {}".format( csp, app_config.CONTENT_SECURITY_POLICY__ADDITIONAL_DIRECTIVES) csp_header_value = csp.format(nonce=csp_nonce) if app_config.CONTENT_SECURITY_POLICY__REPORT_URI: csp_headers.append( ("Report-To", app_config.CONTENT_SECURITY_POLICY__REPORT_URI)) csp_header_value = "{}; report-uri {}".format( csp_header_value, app_config.CONTENT_SECURITY_POLICY__REPORT_URI) csp_headers.append((csp_header_key, csp_header_value)) base_response = Response( headerlist=[("Content-Type", "text/html")] + csp_headers) return render_to_response( self._get_index_file_path(), { "colors": { "primary": ExtendedColor(app_config.APPS_COLORS["primary"]) }, "applications": frontend_apps, "website_title": app_config.WEBSITE__TITLE, "custom_toolbox_files": self.custom_toolbox_files, "cache_token": self.cache_token, "excluded_notifications": app_config.WEB__NOTIFICATIONS__EXCLUDED, "csp_nonce": csp_nonce, "glob": self.glob, }, request=request, response=base_response, )
def applications(self, context, request: TracimRequest, hapic_data=None): """ Get list of alls applications installed in this tracim instance. """ app_config = request.registry.settings['CFG'] app_api = ApplicationApi( app_list=app_list, ) return app_api.get_all()
def sidebar_entries(self) -> typing.List[WorkspaceMenuEntry]: """ get sidebar entries, those depends on activated apps. """ # TODO - G.M - 22-05-2018 - Rework on this in # order to not use hardcoded list # list should be able to change (depending on activated/disabled # apps) app_api = ApplicationApi(app_list) return app_api.get_default_workspace_menu_entry(self.workspace)
def applications(self, context, request: TracimRequest, hapic_data=None): """ Get list of alls applications installed in this tracim instance. """ app_config = request.registry.settings["CFG"] # type: CFG app_api = ApplicationApi(app_list=app_list) applications_in_context = [ app_api.get_application_in_context(app, app_config) for app in app_api.get_all() ] return applications_in_context
def test_get_default_workspace_menu_entry__ok__nominal_case(self): """ Show only enabled app """ app_config = Mock() app_config.APPS_COLORS = {} app_config.APPS_COLORS["primary"] = "#fff" thread = Application( label="Threads", slug="contents/thread", fa_icon="comments-o", is_active=True, config={}, main_route="/ui/workspaces/{workspace_id}/contents?type=thread", app_config=app_config, ) thread.add_content_type( slug="thread", label="Thread", creation_label="Start a topic", available_statuses=content_status_list.get_all(), file_extension=".thread.html", ) markdownpluspage = Application( label="Markdown Plus Documents", # TODO - G.M - 24-05-2018 - Check label slug="contents/markdownpluspage", fa_icon="file-code-o", is_active=False, config={}, main_route= "/ui/workspaces/{workspace_id}/contents?type=markdownpluspage", app_config=app_config, ) markdownpluspage.add_content_type( slug="markdownpage", label="Rich Markdown File", creation_label="Create a Markdown document", available_statuses=content_status_list.get_all(), ) app_api = ApplicationApi(app_list=[thread, markdownpluspage], show_all=False) workspace = Mock() workspace.workspace_id = 12 workspace.agenda_enabled = True default_workspace_menu_entry = app_api.get_default_workspace_menu_entry( workspace=workspace) assert len(default_workspace_menu_entry) == 3 assert default_workspace_menu_entry[ 0].label == dashboard_menu_entry.label assert default_workspace_menu_entry[ 1].label == all_content_menu_entry.label assert default_workspace_menu_entry[2].label == thread.label
def sidebar_entries(self) -> typing.List[WorkspaceMenuEntry]: """ get sidebar entries, those depends on activated apps. """ # TODO - G.M - 22-05-2018 - Rework on this in # order to not use hardcoded list # list should be able to change (depending on activated/disabled # apps) app_api = ApplicationApi( app_list ) return app_api.get_default_workspace_menu_entry(self.workspace)
def check_config_validity(self) -> None: """ Check if config setted is correct """ self._check_global_config_validity() self._check_email_config_validity() self._check_ldap_config_validity() self._check_search_config_validity() app_lib = ApplicationApi(app_list=app_list) for app in app_lib.get_all(): app.check_config(self)
def test_api__get_applications__ok_200__nominal_case(self): """ Get applications list with a registered user. """ self.testapp.authorization = ("Basic", ("*****@*****.**", "*****@*****.**")) res = self.testapp.get("/api/v2/system/applications", status=200) res = res.json_body app_api = ApplicationApi(app_list=app_list) applications = app_api.get_all() assert len(res) == len(applications) for counter, application in enumerate(applications): assert res[counter]["label"] == application.label assert res[counter]["slug"] == application.slug assert res[counter]["fa_icon"] == application.fa_icon assert res[counter]["hexcolor"] == application.hexcolor assert res[counter]["is_active"] == application.is_active assert res[counter]["config"] == application.config
def test_api__get_applications__ok_200__nominal_case(self): """ Get applications list with a registered user. """ self.testapp.authorization = ('Basic', ('*****@*****.**', '*****@*****.**')) res = self.testapp.get('/api/v2/system/applications', status=200) res = res.json_body dbsession = get_tm_session(self.session_factory, transaction.manager) app_api = ApplicationApi(app_list=app_list, ) applications = app_api.get_all() assert len(res) == len(applications) for counter, application in enumerate(applications): assert res[counter]['label'] == application.label assert res[counter]['slug'] == application.slug assert res[counter]['fa_icon'] == application.fa_icon assert res[counter]['hexcolor'] == application.hexcolor assert res[counter]['is_active'] == application.is_active assert res[counter]['config'] == application.config
def load_config(self) -> None: """Parse configuration file and env variables""" self.log_config_header("Global config parameters:") self._load_global_config() self.log_config_header("Limitation config parameters:") self._load_limitation_config() self.log_config_header("Email config parameters:") self._load_email_config() self.log_config_header("LDAP config parameters:") self._load_ldap_config() self.log_config_header("Webdav config parameters:") self._load_webdav_config() self.log_config_header("Search config parameters:") self._load_search_config() app_lib = ApplicationApi(app_list=app_list) for app in app_lib.get_all(): self.log_config_header( '"{label}" app config parameters:'.format(label=app.label)) app.load_config(self)
def test_get_default_workspace_menu_entry__ok__folder_case(self): """ main route for folder is empty, that why it should not be included in default_menu entry :return: """ app_config = Mock() app_config.APPS_COLORS = {} app_config.APPS_COLORS["primary"] = "#fff" folder = DummyApp(label="Folder", slug="contents/folder", fa_icon="folder-o", config={}, main_route="") content_type = TracimContentType( slug="folder", fa_icon=folder.fa_icon, label="Folder", creation_label="Create a folder", available_statuses=content_status_list.get_all(), allow_sub_content=True, minimal_role_content_creation=WorkspaceRoles.CONTENT_MANAGER, app=folder, ) folder.content_types.append(content_type) folder.is_active = True app_api = ApplicationApi(app_list=[folder], show_inactive=False) workspace = Mock() workspace.workspace_id = 12 workspace.agenda_enabled = True default_workspace_menu_entry = app_api.get_default_workspace_menu_entry( workspace=workspace, app_config=app_config) assert len(default_workspace_menu_entry) == 3 assert default_workspace_menu_entry[ 0].label == dashboard_menu_entry.label assert default_workspace_menu_entry[ 1].label == activity_menu_entry.label assert default_workspace_menu_entry[ 2].label == all_content_menu_entry.label
def applications(self, context, request: TracimRequest, hapic_data=None): """ Get list of alls applications installed in this tracim instance. """ app_api = ApplicationApi(app_list=app_list) return app_api.get_all()
def take_app_action(self, parsed_args: argparse.Namespace, app_context: AppEnvironment) -> None: self._session = app_context["request"].dbsession self._app_config = app_context["registry"].settings["CFG"] delete_user_revision = parsed_args.force or parsed_args.delete_revisions delete_owned_sharespaces = (parsed_args.force or parsed_args.best_effort or parsed_args.delete_sharespaces) anonymize_if_required = parsed_args.best_effort or parsed_args.anonymize_if_required if parsed_args.dry_run_mode: print("(!) Running in dry-run mode, no changes will be applied.") app_context["request"].tm.doom() if parsed_args.force: print("(!) Running in force mode") if parsed_args.best_effort: print("(!) Running in best-effort mode") if delete_user_revision: print( "/!\\ Delete all user revisions, database created may be broken /!\\." ) if delete_owned_sharespaces: print("(!) User owned sharespaces will be deleted too.") if anonymize_if_required: print("(!) Will anonymize user if not possible to delete it") if parsed_args.anonymize_name: print('(!) Custom anonymize name choosen is: "{}"'.format( parsed_args.anonymize_name)) print("") deleted_user_ids = set() # typing.Set[int] deleted_workspace_ids = set() # typing.Set[int] with unprotected_content_revision(self._session) as session: uapi = UserApi( config=self._app_config, session=session, current_user=None, show_deleted=True, show_deactivated=True, ) user_list = [] # type: typing.List[User] for login in parsed_args.logins: try: user = uapi.get_one_by_login(login) user_list.append(user) except UserDoesNotExist as exc: print( 'ERROR: user with email/username "{}" does not exist'. format(login)) raise exc print("~~~~") print("Deletion of user from Database") print("~~~~\n") print("~~~~") for user in user_list: cleanup_lib = CleanupLib(session, self._app_config, dry_run_mode=parsed_args.dry_run_mode) deleted_user_ids_result = self._delete_user_database_info( user, force_delete_all_user_revisions=delete_user_revision, anonymize_if_required=anonymize_if_required, delete_owned_workspaces=delete_owned_sharespaces, anonymized_user_display_name=parsed_args.anonymize_name, cleanup_lib=cleanup_lib, ) deleted_user_ids.add(deleted_user_ids_result.user_id) deleted_workspace_ids.update( deleted_user_ids_result.workspace_ids) print("~~~~") print( "deletion of user(s) from database process almost finished, change will be applied at end " "of this script.\n") print("~~~~") print("Deletion of Caldav Agenda\n") app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(AGENDA__APP_SLUG): # INFO - G.M - 2019-12-13 - cleanup agenda at end of process if deleted_workspace_ids: deleted_workspace_ids_str = [ '"{}"'.format(workspace_id) for workspace_id in deleted_workspace_ids ] print("delete agenda of workspaces {}".format( ", ".join(deleted_workspace_ids_str))) for workspace_id in deleted_workspace_ids: try: cleanup_lib.delete_workspace_agenda(workspace_id) except AgendaNotFoundError: print( 'Warning: Cannot delete agenda for workspace "{}", agenda not found. Agenda path may be incorrect or agenda not created' .format(workspace_id)) print(traceback.format_exc()) if deleted_user_ids: deleted_user_ids_str = [ '"{}"'.format(user_id) for user_id in deleted_user_ids ] print("delete agenda of users {}".format( ", ".join(deleted_user_ids_str))) for user_id in deleted_user_ids: try: cleanup_lib.delete_user_agenda(user_id) except AgendaNotFoundError: print( 'Warning: Cannot delete agenda for user "{}", agenda not found. Agenda path may be incorrect or agenda not created' .format(user_id)) print(traceback.format_exc()) else: print( "Warning ! Agenda app not enabled, agenda will not be deleted." ) print("~~~~") print("deletion of Agenda process finished") print("~~~~") if parsed_args.dry_run_mode: print("Finished (dry-run mode, no change applied)") else: print("Finished")
def _content_types(self): app_api = ApplicationApi(self.app_list) content_types = app_api.get_content_types() return content_types
def get(self) -> ApplicationApi: return ApplicationApi(self.app_list)
def _content_types(self) -> List[TracimContentType]: app_api = ApplicationApi(self.app_list) content_types = app_api.get_content_types() return content_types
def web(global_config: OrderedDict, **local_settings) -> Router: """ 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 # Init plugin manager plugin_manager = init_plugin_manager(app_config) settings["plugin_manager"] = plugin_manager 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 tracim_setting_for_beaker["session.httponly"] = app_config.SESSION__HTTPONLY tracim_setting_for_beaker["session.secure"] = app_config.SESSION__SECURE 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_login_header=app_config.REMOTE_USER_HEADER) ) policies.append(CookieSessionAuthentificationPolicy()) policies.append(QueryTokenAuthentificationPolicy()) if app_config.API__KEY: policies.append( ApiTokenAuthentificationPolicy( api_key_header=TRACIM_API_KEY_HEADER, api_user_login_header=TRACIM_API_USER_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 # mechanism in all views. configurator.set_default_permission(TRACIM_DEFAULT_PERM) # Override default request configurator.set_request_factory(TracimRequest) # Pyramids "plugin" include. # Add SqlAlchemy DB init_models(configurator, app_config) # set Hapic context = TracimPyramidContext( 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() configurator.include(session_controller.bind, route_prefix=BASE_API) configurator.include(system_controller.bind, route_prefix=BASE_API) configurator.include(user_controller.bind, route_prefix=BASE_API) configurator.include(account_controller.bind, route_prefix=BASE_API) configurator.include(reset_password_controller.bind, route_prefix=BASE_API) configurator.include(workspace_controller.bind, route_prefix=BASE_API) configurator.include(comment_controller.bind, route_prefix=BASE_API) app_lib = ApplicationApi(app_list=app_list) for app in app_lib.get_all(): app.load_controllers( app_config=app_config, configurator=configurator, route_prefix=BASE_API, context=context ) configurator.scan("tracim_backend.lib.utils.authentification") # 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) if app_config.FRONTEND__SERVE: configurator.include("pyramid_mako") frontend_controller = FrontendController( dist_folder_path=app_config.FRONTEND__DIST_FOLDER_PATH, custom_toolbox_folder_path=app_config.FRONTEND__CUSTOM_TOOLBOX_FOLDER_PATH, cache_token=app_config.FRONTEND__CACHE_TOKEN, ) configurator.include(frontend_controller.bind) # INFO - G.M - 2019-11-27 - Include plugin custom web code plugin_manager.hook.web_include(configurator=configurator, app_config=app_config) hapic.add_documentation_view("/api/doc", "Tracim API", "API of Tracim") return configurator.make_wsgi_app()
def test_get_default_workspace_menu_entry__ok__nominal_case(self): """ Show only enabled app """ app_config = Mock() app_config.APPS_COLORS = {} app_config.APPS_COLORS["primary"] = "#fff" thread = DummyApp( label="Threads", slug="contents/thread", fa_icon="comments-o", config={}, main_route="", ) content_type = TracimContentType( slug="thread", fa_icon=thread.fa_icon, label="Thread", creation_label="Start a topic", available_statuses=content_status_list.get_all(), slug_aliases=["page"], allow_sub_content=False, file_extension=".thread.html", minimal_role_content_creation=WorkspaceRoles.CONTRIBUTOR, app=thread, ) thread.content_types.append(content_type) markdownpluspage = DummyApp( label="Markdown Plus Documents", # TODO - G.M - 24-05-2018 - Check label slug="contents/markdownpluspage", fa_icon="file-code-o", config={}, main_route="", ) content_type = TracimContentType( slug="markdownpage", fa_icon=thread.fa_icon, label="Rich Markdown File", creation_label="Create a Markdown document", available_statuses=content_status_list.get_all(), allow_sub_content=False, file_extension=".md", minimal_role_content_creation=WorkspaceRoles.CONTRIBUTOR, app=thread, ) markdownpluspage.content_types.append(content_type) thread.is_active = True markdownpluspage.is_active = False app_api = ApplicationApi(app_list=[thread, markdownpluspage], show_inactive=False) workspace = Mock() workspace.workspace_id = 12 workspace.agenda_enabled = True default_workspace_menu_entry = app_api.get_default_workspace_menu_entry( workspace=workspace, app_config=app_config) assert len(default_workspace_menu_entry) == 2 assert default_workspace_menu_entry[ 0].label == dashboard_menu_entry.label assert default_workspace_menu_entry[ 1].label == all_content_menu_entry.label