Example #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)
Example #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 do post-update user actions
        """

        # FIXME - G.M - 2019-03-18 - move this code to another place when
        # event mecanism is ready, see https://github.com/tracim/tracim/issues/1487
        # event on_updated_user should start hook use by agenda  app code.

        if self._config.CALDAV__ENABLED:
            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)
Example #3
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)
Example #4
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)
Example #5
0
    def _render_template(self, mako_template_filepath: str, context: dict,
                         translator: Translator) -> str:
        """
        Render mako template with all needed current variables.

        :param mako_template_filepath: file path of mako template
        :param context: dict with template context
        :return: template rendered string
        """
        try:
            template = Template(
                filename=mako_template_filepath,
                default_filters=["html_escape"],
                imports=[
                    "from mako.filters import html_escape",
                    "from lxml.html.diff import htmldiff",
                    "import humanize",
                ],
            )
            return template.render(_=translator.get_translation,
                                   config=self.config,
                                   lang=translator.default_lang,
                                   **context)
        except Exception:
            logger.exception(self, "Failed to render email template")
            raise EmailTemplateError("Failed to render email template")
Example #6
0
    def connect(self):
        if not self._smtp_connection:
            log = "Connecting to SMTP server {}"
            logger.info(self, log.format(self._smtp_config.server))
            if self._smtp_config.use_implicit_ssl:
                self._smtp_connection = smtplib.SMTP_SSL(
                    self._smtp_config.server, self._smtp_config.port
                )
            else:
                self._smtp_connection = smtplib.SMTP(
                    self._smtp_config.server, self._smtp_config.port
                )
            self._smtp_connection.ehlo()

            # TODO - G.M - 2020-04-02 - Starttls usage should be explicit in configuration, see
            # https://github.com/tracim/tracim/issues/2815
            if self._smtp_config.login and not self._smtp_config.use_implicit_ssl:
                try:
                    starttls_result = self._smtp_connection.starttls()

                    if starttls_result[0] == 220:
                        logger.info(self, "SMTP Start TLS OK")

                    log = "SMTP Start TLS return code: {} with message: {}"
                    logger.debug(
                        self, log.format(starttls_result[0], starttls_result[1].decode("utf-8"))
                    )
                except smtplib.SMTPResponseException as exc:
                    log = "SMTP start TLS return error code: {} with message: {}"
                    logger.error(self, log.format(exc.smtp_code, exc.smtp_error.decode("utf-8")))
                except Exception:
                    log = "Unexpected exception during SMTP start TLS process"
                    logger.exception(self, log)

            if self._smtp_config.login:
                try:
                    login_res = self._smtp_connection.login(
                        self._smtp_config.login, self._smtp_config.password
                    )

                    if login_res[0] == 235:
                        logger.info(self, "SMTP Authentication Successful")
                    if login_res[0] == 503:
                        logger.info(self, "SMTP Already Authenticated")

                    log = "SMTP login return code: {} with message: {}"
                    logger.debug(self, log.format(login_res[0], login_res[1].decode("utf-8")))
                except smtplib.SMTPAuthenticationError as exc:
                    log = "SMTP auth return error code: {} with message: {}"
                    logger.error(self, log.format(exc.smtp_code, exc.smtp_error.decode("utf-8")))
                    logger.error(
                        self, "check your auth params combinaison " "(login/password) for SMTP"
                    )
                except smtplib.SMTPResponseException as exc:
                    log = "SMTP login return error code: {} with message: {}"
                    logger.error(self, log.format(exc.smtp_code, exc.smtp_error.decode("utf-8")))
                except Exception:
                    log = "Unexpected exception during SMTP login"
                    logger.exception(self, log)
Example #7
0
    def send_mail(self, message: MIMEMultipart):
        if not self._is_active:
            log = "Not sending email to {} (service disabled)"
            logger.info(self, log.format(message["To"]))
        else:
            self.connect()  # Actually, this connects to SMTP only if required
            logger.info(self, "Sending email to {}".format(message["To"]))
            # TODO - G.M - 2019-01-29 - optimisize this code, we should not send
            # email if connection has failed.
            send_action = "{:8s}".format("SENT")
            failed_action = "{:8s}".format("SENDFAIL")
            action = send_action
            try:
                send_message_result = self._smtp_connection.send_message(message)
                # INFO - G.M - 2019-01-29 - send_message return if not failed,
                # dict of refused recipients.

                if send_message_result == {}:
                    logger.debug(self, "One mail correctly sent using SMTP.")
                else:
                    # INFO - G.M - 2019-01-29 - send_message_result != {}
                    # case should not happened
                    # as we send not mail with multiple recipient at the same
                    # time. send_message will not raise exception
                    # just if some recipient work and some other failed.
                    # TODO - G.M - 2019-01-29 - better support for multirecipient email
                    log = "Mail could not be send to some recipient: {}"
                    logger.debug(self, log.format(send_message_result))
                    action = failed_action

            except smtplib.SMTPException:
                log = "SMTP sending message return error"
                logger.exception(self, log)
                action = failed_action
            except Exception:
                log = "Unexpected exception during sending email message using SMTP"
                logger.exception(self, log)
                action = failed_action

            from tracim_backend.lib.mail_notifier.notifier import EmailManager

            if action == send_action:
                msg = "an email was sended to {}".format(message["To"])
            else:
                msg = "fail to send email to {}".format(message["To"])

            EmailManager.log_email_notification(
                msg=msg,
                action=action,
                email_recipient=message["To"],
                email_subject=message["Subject"],
                config=self.config,
            )
Example #8
0
 def take_action(self, parsed_args: argparse.Namespace) -> None:
     try:
         super(AppContextCommand, self).take_action(parsed_args)
         self._setup_logging(parsed_args)
         if self.auto_setup_context:
             with bootstrap(parsed_args.config_file) as app_context:
                 with app_context["request"].tm:
                     self.take_app_action(parsed_args, app_context)
     except Exception as exc:
         logger.exception(self, exc)
         print("Something goes wrong during command")
         raise exc
Example #9
0
 def take_action(self, parsed_args: argparse.Namespace) -> None:
     try:
         super(AppContextCommand, self).take_action(parsed_args)
         self._setup_logging(parsed_args)
         if self.auto_setup_context:
             with bootstrap(parsed_args.config_file) as app_context:
                 with app_context["request"].tm:
                     self.take_app_action(parsed_args, app_context)
     except transaction.interfaces.DoomedTransaction:
         # The code willingly doomed the transaction, do not display an error
         pass
     except Exception as exc:
         logger.exception(self, exc)
         print("Something goes wrong during command: {}".format(exc))
         raise exc
Example #10
0
 def _check_agenda_exist(self, agenda_url) -> bool:
     try:
         response = requests.get(agenda_url)
     except requests.exceptions.ConnectionError as exc:
         logger.error(
             self,
             "Cannot check agenda existence, connection error to radicale server"
         )
         logger.exception(self, exc)
         raise AgendaServerConnectionError() from exc
     if response.status_code < 400:
         return True
     else:
         # TODO - G.M - 2019-03-13 - Better deal with other error code
         return False
Example #11
0
 def index_all_content(self) -> IndexedContentsResults:
     """
     Index/update all content in current index of ElasticSearch
     """
     content_api = ContentApi(
         session=self._session,
         config=self._config,
         current_user=self._user,
         show_archived=True,
         show_active=True,
         show_deleted=True,
     )
     contents = content_api.get_all()
     content_ids_to_index = []  # type: typing.List[int]
     errored_indexed_contents_ids = []  # type: typing.List[int]
     for content in contents:
         content_in_context = ContentInContext(
             content, config=self._config, dbsession=self._session
         )
         content_ids_to_index.append(content_in_context.content_id)
         try:
             self.index_content(content_in_context)
         except ConnectionError as exc:
             logger.error(
                 self,
                 "connexion error issue with elasticsearch during indexing of content {}".format(
                     content_in_context.content_id
                 ),
             )
             logger.exception(self, exc)
             errored_indexed_contents_ids.append(content_in_context.content_id)
         except Exception as exc:
             logger.error(
                 self,
                 "something goes wrong during indexing of content {}".format(
                     content_in_context.content_id
                 ),
             )
             logger.exception(self, exc)
             errored_indexed_contents_ids.append(content_in_context.content_id)
     return IndexedContentsResults(content_ids_to_index, errored_indexed_contents_ids)
Example #12
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
        """

        # 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 mecanism is ready, see https://github.com/tracim/tracim/issues/1487
        # event on_created_user should start hook use by agenda  app code.

        if self._config.CALDAV__ENABLED:
            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 {} is just created but his own agenda already exist !!"
                        .format(user.user_id),
                    )
            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)
Example #13
0
    def _notify_tracim(self, mails: typing.List[DecodedMail],
                       imapc: imapclient.IMAPClient) -> None:
        """
        Send http request to tracim endpoint
        :param mails: list of mails to send
        :return: none
        """
        logger.debug(self,
                     "Notify tracim about {} new responses".format(len(mails)))
        # TODO BS 20171124: Look around mail.get_from_address(), mail.get_key()
        # , mail.get_body() etc ... for raise InvalidEmailError if missing
        #  required informations (actually get_from_address raise IndexError
        #  if no from address for example) and catch it here
        while mails:
            mail = mails.pop()
            try:
                method, endpoint, json_body_dict = self._create_comment_request(
                    mail)
            except NoKeyFound:
                log = "Failed to create comment request due to missing specialkey in mail"
                logger.exception(self, log)
                continue
            except EmptyEmailBody:
                log = "Empty body, skip mail"
                logger.error(self, log)
                continue
            except AutoReplyEmailNotAllowed:
                log = "Autoreply mail, skip mail"
                logger.warning(self, log)
                continue
            except Exception:
                log = "Failed to create comment request in mail fetcher error"
                logger.exception(self, log)
                continue

            try:
                self._send_request(
                    mail=mail,
                    imapc=imapc,
                    method=method,
                    endpoint=endpoint,
                    json_body_dict=json_body_dict,
                )
            except requests.exceptions.Timeout:
                log = "Timeout error to transmit fetched mail to tracim"
                logger.exception(self, log)
            except requests.exceptions.RequestException:
                log = "Fail to transmit fetched mail to tracim"
                logger.exception(self, log)
Example #14
0
    def execute_created_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 creation workspace actions
        """

        # FIXME - G.M - 2019-03-18 - move this code to another place when
        # event mecanism is ready, see https://github.com/tracim/tracim/issues/1487
        # event on_created_workspace should start hook use by agenda app code.

        # 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.lib.agenda.agenda import AgendaApi

        if self._config.CALDAV__ENABLED:
            if workspace.agenda_enabled:
                agenda_api = AgendaApi(current_user=self._user,
                                       session=self._session,
                                       config=self._config)
                try:
                    agenda_already_exist = agenda_api.ensure_workspace_agenda_exists(
                        workspace)
                    if agenda_already_exist:
                        logger.warning(
                            self,
                            "workspace {} is just created but it own agenda already exist !!"
                            .format(workspace.workspace_id),
                        )
                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)
Example #15
0
    def _render_template(
            self,
            mako_template_filepath: str,
            context: dict,
            translator: Translator
    ) -> str:
        """
        Render mako template with all needed current variables.

        :param mako_template_filepath: file path of mako template
        :param context: dict with template context
        :return: template rendered string
        """
        try:
            template = Template(filename=mako_template_filepath)
            return template.render(
                _=translator.get_translation,
                config=self.config,
                **context
            )
        except Exception as exc:
            logger.exception(self, 'Failed to render email template: {}'.format(exc.__str__()))
            raise EmailTemplateError('Failed to render email template: {}'.format(exc.__str__()))
Example #16
0
    def run(self) -> None:
        logger.info(self, "Starting MailFetcher")
        while self._is_active:
            imapc = None
            sleep_after_connection = True
            try:
                imapc = imapclient.IMAPClient(
                    self.host,
                    self.port,
                    ssl=self.use_ssl,
                    timeout=MAIL_FETCHER_CONNECTION_TIMEOUT)
                imapc.login(self.user, self.password)

                logger.debug(self, "Select folder {}".format(self.folder))
                imapc.select_folder(self.folder)

                # force renew connection when deadline is reached
                deadline = time.time() + self.connection_max_lifetime
                while True:
                    if not self._is_active:
                        logger.warning(self, "Mail Fetcher process aborted")
                        sleep_after_connection = False
                        break

                    if time.time() > deadline:
                        logger.debug(
                            self,
                            "MailFetcher Connection Lifetime limit excess"
                            ", Try Re-new connection",
                        )
                        sleep_after_connection = False
                        break

                    # check for new mails
                    self._check_mail(imapc)

                    if self.use_idle and imapc.has_capability("IDLE"):
                        # IDLE_mode wait until event from server
                        logger.debug(self, "wait for event(IDLE)")
                        imapc.idle()
                        imapc.idle_check(
                            timeout=MAIL_FETCHER_IDLE_RESPONSE_TIMEOUT)
                        imapc.idle_done()
                    else:
                        if self.use_idle and not imapc.has_capability("IDLE"):
                            log = ("IDLE mode activated but server do not"
                                   "support it, use polling instead.")
                            logger.warning(self, log)

                        if self.burst:
                            self.stop()
                            break
                        # normal polling mode : sleep a define duration
                        logger.debug(self,
                                     "sleep for {}".format(self.heartbeat))
                        time.sleep(self.heartbeat)

                    if self.burst:
                        self.stop()
                        break
            # Socket
            except (socket.error, socket.gaierror, socket.herror):
                log = "Socket fail with IMAP connection"
                logger.exception(self, log)
            except socket.timeout:
                log = "Socket timeout on IMAP connection"
                logger.exception(self, log)
            # SSL
            except ssl.SSLError:
                log = "SSL error on IMAP connection"
                logger.exception(self, log)
            except ssl.CertificateError:
                log = "SSL Certificate verification failed on IMAP connection"
                logger.exception(self, log)
            # Filelock
            except filelock.Timeout:
                log = "Mail Fetcher Lock Timeout"
                logger.warning(self, log, exc_info=True)

            # IMAP
            # TODO - G.M - 10-01-2017 - Support imapclient exceptions
            # when Imapclient stable will be 2.0+

            except BadIMAPFetchResponse:
                log = ("Imap Fetch command return bad response."
                       "Is someone else connected to the mailbox ?")
                logger.exception(self, log)
            # Others
            except Exception:
                log = "Mail Fetcher error"
                logger.exception(self, log)

            finally:
                # INFO - G.M - 2018-01-09 - Connection closing
                # Properly close connection according to
                # https://github.com/mjs/imapclient/pull/279/commits/043e4bd0c5c775c5a08cb5f1baa93876a46732ee
                # TODO : Use __exit__ method instead when imapclient stable will
                # be 2.0+ .
                if imapc:
                    logger.debug(self, "Try logout")
                    try:
                        imapc.logout()
                    except Exception:
                        try:
                            imapc.shutdown()
                        except Exception:
                            log = "Can't logout, connection broken ?"
                            logger.exception(self, log)

            if self.burst:
                self.stop()
                break

            if sleep_after_connection:
                logger.debug(self, "sleep for {}".format(self.heartbeat))
                time.sleep(self.heartbeat)

        log = "Mail Fetcher stopped"
        logger.debug(self, log)
Example #17
0
    def notify_content_update(self, content: Content):

        if content.get_last_action().id not \
                in self.config.EMAIL_NOTIFICATION_NOTIFIED_EVENTS:
            logger.info(
                self,
                'Skip email notification for update of content {}'
                'by user {} (the action is {})'.format(
                    content.content_id,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id
                )
            )
            return

        logger.info(self,
                    'About to email-notify update'
                    'of content {} by user {}'.format(
                        content.content_id,
                        # Below: 0 means "no user"
                        self._user.user_id if self._user else 0
                    )
        )

        if content.type not \
                in self.config.EMAIL_NOTIFICATION_NOTIFIED_CONTENTS:
            logger.info(
                self,
                'Skip email notification for update of content {}'
                'by user {} (the content type is {})'.format(
                    content.type,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id
                )
            )
            return

        logger.info(self,
                    'About to email-notify update'
                    'of content {} by user {}'.format(
                        content.content_id,
                        # Below: 0 means "no user"
                        self._user.user_id if self._user else 0
                    )
        )

        ####
        #
        # INFO - D.A. - 2014-11-05 - Emails are sent through asynchronous jobs.
        # For that reason, we do not give SQLAlchemy objects but ids only
        # (SQLA objects are related to a given thread/session)
        #
        try:
            if self.config.EMAIL_NOTIFICATION_PROCESSING_MODE.lower() == self.config.CST.ASYNC.lower():
                logger.info(self, 'Sending email in ASYNC mode')
                # TODO - D.A - 2014-11-06
                # This feature must be implemented in order to be able to scale to large communities
                raise NotImplementedError('Sending emails through ASYNC mode is not working yet')
            else:
                logger.info(self, 'Sending email in SYNC mode')
                EmailManager(
                    self._smtp_config,
                    self.config,
                    self.session,
                ).notify_content_update(self._user.user_id, content.content_id)
        except Exception as e:
            # TODO - G.M - 2018-08-27 - Do Better catching for exception here
            logger.error(self, 'Exception catched during email notification: {}'.format(e.__str__()))
            logger.exception(self, e)
Example #18
0
    def take_app_action(self, parsed_args: argparse.Namespace,
                        app_context: AppEnvironment) -> None:
        # TODO - G.M - 05-04-2018 -Refactor this in order
        # to not setup object var outside of __init__ .
        self._session = app_context["request"].dbsession
        self._app_config = app_context["registry"].settings["CFG"]
        self._user_api = UserApi(current_user=None,
                                 session=self._session,
                                 config=self._app_config)
        self._workspace_api = WorkspaceApi(current_user=None,
                                           force_role=True,
                                           session=self._session,
                                           config=self._app_config)
        self._agenda_api = AgendaApi(current_user=None,
                                     session=self._session,
                                     config=self._app_config)

        # INFO - G.M - 2019-03-13 - check users agendas
        users = self._user_api.get_all()
        nb_error_agenda_access = 0
        for user in users:
            try:
                already_exist = self._agenda_api.ensure_user_agenda_exists(
                    user)
                if not already_exist:
                    print("New created agenda for user {}".format(user))
            except CannotCreateAgenda as exc:
                nb_error_agenda_access += 1
                print("Cannot create agenda for user {}".format(user.user_id))
                logger.exception(self, exc)
            except AgendaServerConnectionError as exc:
                nb_error_agenda_access += 1
                print("Cannot access to agenda server: connection error.")
                logger.exception(self, exc)
            except Exception as exc:
                nb_error_agenda_access += 1
                print("Something goes wrong during agenda create/update")
                logger.exception(self, exc)
        nb_user_agendas = len(users)
        nb_verified_user_agenda = len(users) - nb_error_agenda_access
        print("{}/{} users agenda verified".format(nb_verified_user_agenda,
                                                   nb_user_agendas))

        # # INFO - G.M - 2019-03-13 - check workspaces agendas
        workspaces = self._workspace_api.get_all()
        nb_error_agenda_access = 0
        nb_workspaces = 0
        nb_agenda_enabled_workspace = 0
        for workspace in workspaces:
            nb_workspaces += 1
            if workspace.agenda_enabled:
                nb_agenda_enabled_workspace += 1
                try:
                    already_exist = self._agenda_api.ensure_workspace_agenda_exists(
                        workspace)
                    if not already_exist:
                        print("New created agenda for workspace {}".format(
                            workspace.workspace_id))
                except CannotCreateAgenda as exc:
                    print("Cannot create agenda for workspace {}".format(
                        workspace.workspace_id))
                    logger.exception(self, exc)
                except AgendaServerConnectionError as exc:
                    nb_error_agenda_access += 1
                    print("Cannot access to agenda server: connection error.")
                    logger.exception(self, exc)
        nb_verified_workspace_agenda = nb_agenda_enabled_workspace - nb_error_agenda_access
        nb_workspace_without_agenda_enabled = nb_workspaces - nb_agenda_enabled_workspace
        print(
            "{}/{} workspace agenda verified ({} workspace without agenda feature enabled)"
            .format(
                nb_verified_workspace_agenda,
                nb_agenda_enabled_workspace,
                nb_workspace_without_agenda_enabled,
            ))
Example #19
0
    def notify_content_update(self, content: Content):

        if content.get_last_action(
        ).id not in self.config.EMAIL__NOTIFICATION__NOTIFIED_EVENTS:
            logger.info(
                self,
                "Skip email notification for update of content {}"
                "by user {} (the action is {})".format(
                    content.content_id,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id,
                ),
            )
            return

        logger.info(
            self,
            "About to email-notify update"
            "of content {} by user {}".format(
                content.content_id,
                # Below: 0 means "no user"
                self._user.user_id if self._user else 0,
            ),
        )

        if content.type not in self.config.EMAIL__NOTIFICATION__NOTIFIED_CONTENTS:
            logger.info(
                self,
                "Skip email notification for update of content {}"
                "by user {} (the content type is {})".format(
                    content.type,
                    # below: 0 means "no user"
                    self._user.user_id if self._user else 0,
                    content.get_last_action().id,
                ),
            )
            return

        logger.info(
            self,
            "About to email-notify update"
            "of content {} by user {}".format(
                content.content_id,
                # Below: 0 means "no user"
                self._user.user_id if self._user else 0,
            ),
        )

        ####
        #
        # INFO - D.A. - 2014-11-05 - Emails are sent through asynchronous jobs.
        # For that reason, we do not give SQLAlchemy objects but ids only
        # (SQLA objects are related to a given thread/session)
        #
        try:
            if (self.config.EMAIL__NOTIFICATION__PROCESSING_MODE.lower() ==
                    self.config.CST.ASYNC.lower()):
                logger.info(self, "Sending email in ASYNC mode")
                # TODO - D.A - 2014-11-06
                # This feature must be implemented in order to be able to scale to large communities
                raise NotImplementedError(
                    "Sending emails through ASYNC mode is not working yet")
            else:
                logger.info(self, "Sending email in SYNC mode")
                EmailManager(self._smtp_config, self.config,
                             self.session).notify_content_update(
                                 self._user.user_id, content.content_id)
        except Exception:
            logger.exception(self,
                             "Exception catched during email notification")