Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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,
            }
        )
Пример #4
0
    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,
            },
        )
Пример #5
0
    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,
                ),
            )
Пример #6
0
 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()
Пример #7
0
 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
Пример #8
0
    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,
        )
Пример #9
0
    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)
Пример #10
0
 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 ""
Пример #11
0
    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
Пример #12
0
    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,
        )
Пример #13
0
 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()
Пример #14
0
 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)
Пример #15
0
 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
Пример #16
0
    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
Пример #17
0
 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)
Пример #18
0
    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)
Пример #19
0
 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
Пример #20
0
 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
Пример #21
0
    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)
Пример #22
0
    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
Пример #23
0
 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()
Пример #24
0
    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")
Пример #25
0
 def _content_types(self):
     app_api = ApplicationApi(self.app_list)
     content_types = app_api.get_content_types()
     return content_types
Пример #26
0
 def get(self) -> ApplicationApi:
     return ApplicationApi(self.app_list)
Пример #27
0
 def _content_types(self) -> List[TracimContentType]:
     app_api = ApplicationApi(self.app_list)
     content_types = app_api.get_content_types()
     return content_types
Пример #28
0
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()
Пример #29
0
    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