示例#1
0
class ResetPasswordFormSchema(model.Schema):
    new_password = schema.Password(title=_("label_new_password",
                                           default="Desired password"), )
    new_password_confirmation = schema.Password(title=_(
        "label_confirm_password", default="Confirm your password"), )

    @invariant
    def validate_same_value(data):
        if data.new_password != data.new_password_confirmation:
            raise Invalid(
                _("Password doesn't compare with confirmation value"))
示例#2
0
    def do_save(self):
        """Execute the save action"""
        (data, errors) = self.extractData()
        if errors:
            for err in errors:
                if isinstance(err.error, Exception):
                    self.error = _("error_password_mismatch",
                                   default="Passwords do not match")
            return

        key = self.key
        ppr = api.portal.get_tool("portal_password_reset")

        try:
            ppr.verifyKey(key)
        except InvalidRequestError:
            self.error = _("Invalid security token, try to request a new one")
            return

        login_view = api.content.get_view(
            name="login",
            context=self.context,
            request=self.request,
        )
        error = login_view.check_password_policy(data["new_password"])
        if error:
            self.error = error
            return

        account_id, expiry = ppr._requests.get(key)
        if ppr.expired(expiry):
            del ppr._requests[key]
            ppr._p_changed = 1
            self.error = _("This URL has expired, try to request a new one")
            return

        account = Session().query(Account).filter(
            Account.id == account_id).one()
        account.password = data["new_password"]

        # clean out the request
        del ppr._requests[key]
        ppr._p_changed = 1

        current_url = self.context.absolute_url()
        return self.redirect(
            "{}/@@login?{}".format(current_url,
                                   urlencode(dict(came_from=current_url))),
            msg=_("Your password was successfully changed."),
        )
示例#3
0
 def validate(self):
     previous_question_id = self.previous_question_id
     if not previous_question_id:
         return
     training = self.get_or_create_training()
     try:
         answers = loads(training.answers)
     except ValueError:
         answers = {}
     if all([answer is None for answer in answers]):
         raise Unauthorized(
             _("You should start the training from the beginning"))
     if answers.get(previous_question_id) is None:
         raise Unauthorized(_("It seems you missed a slide"))
示例#4
0
class RisksOverview(Status):
    """Implements the "Overview of Risks" report, see #10967"""

    label = _("Overview of risks")

    def is_skipped_from_risk_list(self, risk):
        if risk.identification == "yes":
            return True
示例#5
0
 def update(self):
     super(ResetPasswordForm, self).update()
     key = self.key
     ppr = api.portal.get_tool("portal_password_reset")
     try:
         ppr.verifyKey(key)
     except InvalidRequestError:
         self.error = _("Invalid security token, try to request a new one")
示例#6
0
 def get_pat_messages_above_title(self):
     """List of messages we want to display above the risk assesment title"""
     if not self.webhelpers.can_edit_session:
         link_download_section = _(
             "no_translate_link_download_section",
             default="<a href='%s/@@report'>${text_download_section}</a>" %
             self.context.absolute_url(),
             mapping={"text_download_section": _("download section")},
         )
         message = _(
             "You don't have edit rights for this risk assesment, "
             "but you can download "
             "this risk assessment in various forms in the ${download_section}.",
             mapping={"download_section": link_download_section},
         )
         return [api.portal.translate(message)]
     return []
示例#7
0
 def pat_validation_messages(self):
     lang = getattr(self.request, "LANGUAGE", "en")
     if "-" in lang:
         elems = lang.split("-")
         lang = "{0}_{1}".format(elems[0], elems[1].upper())
     messages = {
         "message-date":
         translate(
             _("error_validation_date",
               default="This value must be a valid date"),
             target_language=lang,
         ),
         "message-datetime":
         translate(
             _(
                 "error_validation_datetime",
                 default="This value must be a valid date and time",
             ),
             target_language=lang,
         ),
         "message-email":
         translate(
             _(
                 "error_validation_email",
                 default="This value must be a valid email address",
             ),
             target_language=lang,
         ),
         "message-number":
         translate(
             _("error_validation_number",
               default="This value must be a number"),
             target_language=lang,
         ),
         "message-required":
         translate(
             _("message_field_required",
               default="Please fill out this field."),
             target_language=lang,
         ),
     }
     return "; ".join([
         "{key}: {value}".format(key=key, value=value)
         for key, value in messages.items()
     ])
示例#8
0
    def send_mail(self, email):
        account = Session.query(Account).filter(
            Account.loginname == email).first()
        if not account:
            # We returned True even if the account
            # does not exist to not leak any information
            return True

        ppr = api.portal.get_tool("portal_password_reset")
        # Clean out previous requests by this user
        for token, value in ppr._requests.items():
            if value[0] == account.id:
                del ppr._requests[token]
                ppr._p_changed = 1

        reset_info = ppr.requestReset(account.id)
        reset_info["host"] = self.get_remote_host()
        mailhost = api.portal.get_tool("MailHost")
        body = self.email_template(**reset_info)
        subject = translate(
            _("OiRA password reset instructions"),
            context=self.request,
        )
        mail = CreateEmailTo(
            self.email_from_name,
            self.email_from_address,
            account.email,
            subject,
            body,
        )

        try:
            mailhost.send(
                mail,
                account.email,
                self.email_from_address,
                immediate=True,
            )
            logger.info(
                "Sent password reset instructions to %s",
                account.email,
            )
        except MailHostError as e:
            msg = (
                "MailHost error sending password reset instructions to {}: {}"
            ).format(account.email, e)
            return self.log_error(msg)
        except smtplib.SMTPException as e:
            msg = (
                "smtplib error sending password reset instructions to {}: {}"
            ).format(account.email, e)
            return self.log_error(msg)
        except socket.error as e:
            msg = ("Socket error sending password reset instructions to {}: {}"
                   ).format(account.email, e[1])
            return self.log_error(msg)
        return True
示例#9
0
 def get_progress_indicator_title(self, completion_percentage=None):
     if completion_percentage is None and self.traversed_session is not None:
         completion_percentage = self.traversed_session.session.completion_percentage
     title = _(
         "progress_indicator_title",
         default="${completion_percentage}% Complete",
         mapping={"completion_percentage": completion_percentage or 0},
     )
     return api.portal.translate(title)
示例#10
0
class IStartFormSchema(model.Schema):
    title = schema.TextLine(
        title=_("label_session_title",
                default="Enter a title for your Risk Assessment"),
        required=True,
        description=_(
            "session_title_tooltip",
            default="Once you have started an OiRA tool "
            "session, you will be able to stop before the end. You can restart it "
            "again at a later date by selecting the title of the OiRA tool session. "
            "You can save more than one session, provided you have given them "
            "different title names. Please remember your e-mail address, password "
            "and the title that you have given the OiRA tool session. By clicking "
            "on the Logout button, you are logged out actively. You are also logged "
            "out if you close your Browser. For security reasons it is better to "
            "actively log out.",
        ),
    )
示例#11
0
    def profile_questions(self):
        """Return information for all profile questions in this survey.

        The data is returned as a list of dictionaries with the following
        keys:

        - ``id``: object id of the question
        - ``title``: title of the question
        - ``question``: question about the general occurance
        - ``label_multiple_present``: question about single or multiple
          occurance
        - ``label_single_occurance``: label for single occurance
        - ``label_multiple_occurances``: label for multiple occurance
        """
        return [{
            "id":
            child.id,
            "title":
            child.title,
            "question":
            child.question or child.title,
            "use_location_question":
            getattr(child, "use_location_question", True),
            "label_multiple_present":
            getattr(
                child,
                "label_multiple_present",
                _("Does this happen in multiple places?"),
            ),
            "label_single_occurance":
            getattr(
                child,
                "label_single_occurance",
                _("Enter the name of the location"),
            ),
            "label_multiple_occurances":
            getattr(
                child,
                "label_multiple_occurances",
                _("Enter the names of each location"),
            ),
        } for child in self.context.ProfileQuestions()]
示例#12
0
 def sector_title(self):
     """Return the title to use for the current sector. If the current
     context is not in a sector return the agency name instead.
     """
     sector = self.sector
     if sector is not None and getattr(aq_base(sector), "logo",
                                       None) is not None:
         return sector.Title()
     else:
         return _(
             "title_tool",
             default="OiRA - Online interactive Risk Assessment",
         )
示例#13
0
    def clone(self):
        """Clone this session and redirect to the start view"""
        if not self.webhelpers.can_view_session:
            # The user cannot call this view to go the sessions overview.
            return self.request.response.redirect(self.webhelpers.client_url)

        new_session = self.get_cloned_session()
        api.portal.show_message(_("The risk assessment has been cloned"),
                                self.request, "success")
        target = "{contexturl}/++session++{sessionid}/@@start?new_clone=1".format(
            contexturl=aq_parent(self.context).absolute_url(),
            sessionid=new_session.id)
        self.request.response.redirect(target)
示例#14
0
    def __call__(self):
        if not self.webhelpers.can_delete_session:
            raise Unauthorized()

        Session.delete(self.context.session)
        api.portal.show_message(
            _(
                "Session `${name}` has been deleted.",
                mapping={"name": self.context.session.title},
            ),
            self.request,
            "success",
        )
        self.request.response.redirect(self.webhelpers.country_url)
示例#15
0
    def __call__(self):
        if not self.webhelpers.can_archive_session:
            raise Unauthorized()

        session = self.context.session
        session.archived = localized_now()
        self.notify_modified()
        api.portal.show_message(
            _("Session `${name}` has been archived.",
              mapping={"name": session.title}),
            self.request,
            "success",
        )
        return self.redirect()
示例#16
0
 def extra_text(self):
     have_extra = api.portal.get_registry_record(
         "euphorie.extra_text_identification", default="")
     if not have_extra:
         return None
     lang = getattr(self.request, "LANGUAGE", "en")
     # Special handling for Flemish, for which LANGUAGE is "nl-be". For
     # translating the date under plone locales, we reduce to generic "nl".
     # For the specific oira translation, we rewrite to "nl_BE"
     if "-" in lang:
         elems = lang.split("-")
         lang = "{0}_{1}".format(elems[0], elems[1].upper())
     return translate(_("extra_text_identification", default=""),
                      target_language=lang)
示例#17
0
 def __call__(self):
     if not self.webhelpers.can_edit_session:
         return self.request.response.redirect(self.context.absolute_url() +
                                               "/@@start")
     if not self.next_url:
         msg = _(
             "There is not enough information to proceed to the identification phase"
         )
         api.portal.show_message(msg, self.request, "error")
         return self.request.response.redirect(self.context.absolute_url() +
                                               "/@@start")
     utils.setLanguage(self.request, self.survey, self.survey.language)
     if self.webhelpers.use_involve_phase:
         self.request.RESPONSE.redirect(self.next_url)
     else:
         return super(Identification, self).__call__()
示例#18
0
 def do_next(self):
     data, error = self.extractData()
     if error:
         return
     email = data.get("email")
     if not self.send_mail(email):
         return
     msg = _(
         "message_password_recovery_email_sent",
         default="An email will be sent to ${email} "
         "if we can find an account for this email address. Please use the "
         "link inside the e-mail to reset your password.",
         mapping={"email": email},
     )
     webhelpers = api.content.get_view(name="webhelpers",
                                       context=self.context,
                                       request=self.request)
     redir_url = webhelpers.get_came_from(
         default=self.context.absolute_url())
     if not redir_url.endswith("login"):
         redir_url = "{0}/@@login?{1}#login".format(
             redir_url, urlencode({"came_from": redir_url}))
     self.redirect(redir_url, msg)
示例#19
0
 def closetext(self):
     return api.portal.translate(_("button_close", default="Close"))
示例#20
0
    def get_cloned_session(self):
        sql_session = Session
        old_session = self.session
        new_session = sql_clone(
            old_session,
            skip={
                "id",
                "created",
                "modified",
                "last_modifier_id",
                "company",
                "published",
                "group_id",
                "archived",
            },
            session=sql_session,
        )
        lang = getattr(self.request, "LANGUAGE", "en")
        new_session.title = "{}: {}".format(
            translate(_("prefix_cloned_title", default="COPY"),
                      target_language=lang),
            new_session.title,
        )
        account = self.webhelpers.get_current_account()
        new_session.group = account.group
        new_session.modified = new_session.created = datetime.now()
        new_session.account = account
        if old_session.company:
            new_session.company = sql_clone(old_session.company,
                                            skip={"id", "session"},
                                            session=sql_session)

        risk_module_skipped_attributes = {
            "id",
            "session",
            "sql_module_id",
            "parent_id",
            "session_id",
            "sql_risk_id",
            "risk_id",
        }
        module_mapping = {}

        old_modules = sql_session.query(Module).filter(
            SurveyTreeItem.session == old_session)
        for old_module in old_modules:
            new_module = sql_clone(old_module,
                                   skip=risk_module_skipped_attributes,
                                   session=sql_session)
            module_mapping[old_module.id] = new_module
            new_module.session = new_session

        old_risks = sql_session.query(Risk).filter(
            SurveyTreeItem.session == old_session)
        for old_risk in old_risks:
            new_risk = sql_clone(old_risk,
                                 skip=risk_module_skipped_attributes,
                                 session=sql_session)
            new_risk.parent_id = module_mapping[old_risk.parent_id].id
            new_risk.session = new_session

            for old_plan in old_risk.action_plans:
                new_plan = sql_clone(old_plan,
                                     skip={"id", "risk_id"},
                                     session=sql_session)
                new_plan.risk = new_risk
        notify(ObjectModifiedEvent(new_session))
        return new_session
示例#21
0
 def validate_same_value(data):
     if data.new_password != data.new_password_confirmation:
         raise Invalid(
             _("Password doesn't compare with confirmation value"))
示例#22
0
class ResetPasswordForm(BaseForm):
    ignoreContext = True
    schema = ResetPasswordFormSchema

    label = _(
        "title_reset_password_form",
        default="Reset password",
    )
    description = _(
        "description_reset_password_form",
        default="",
    )
    button_label = _("Save changes")

    def update(self):
        super(ResetPasswordForm, self).update()
        key = self.key
        ppr = api.portal.get_tool("portal_password_reset")
        try:
            ppr.verifyKey(key)
        except InvalidRequestError:
            self.error = _("Invalid security token, try to request a new one")

    def publishTraverse(self, request, name):
        return self

    @property
    @memoize_contextless
    def key(self):
        """Extract the key from the URL"""
        return self.request.getURL().rpartition("/")[-1]

    def do_save(self):
        """Execute the save action"""
        (data, errors) = self.extractData()
        if errors:
            for err in errors:
                if isinstance(err.error, Exception):
                    self.error = _("error_password_mismatch",
                                   default="Passwords do not match")
            return

        key = self.key
        ppr = api.portal.get_tool("portal_password_reset")

        try:
            ppr.verifyKey(key)
        except InvalidRequestError:
            self.error = _("Invalid security token, try to request a new one")
            return

        login_view = api.content.get_view(
            name="login",
            context=self.context,
            request=self.request,
        )
        error = login_view.check_password_policy(data["new_password"])
        if error:
            self.error = error
            return

        account_id, expiry = ppr._requests.get(key)
        if ppr.expired(expiry):
            del ppr._requests[key]
            ppr._p_changed = 1
            self.error = _("This URL has expired, try to request a new one")
            return

        account = Session().query(Account).filter(
            Account.id == account_id).one()
        account.password = data["new_password"]

        # clean out the request
        del ppr._requests[key]
        ppr._p_changed = 1

        current_url = self.context.absolute_url()
        return self.redirect(
            "{}/@@login?{}".format(current_url,
                                   urlencode(dict(came_from=current_url))),
            msg=_("Your password was successfully changed."),
        )

    @button.buttonAndHandler(_("Save"))
    def save_handler(self, action):
        """Check if the security token is correct and if it is
        change the account password with the provided value
        """
        self.do_save()

    @button.buttonAndHandler(_("Cancel"))
    def handleCancel(self, action):
        self.redirect(self.context.absolute_url())
示例#23
0
class ResetPasswordRequest(BaseForm):
    """Request a link to reset the password"""

    ignoreContext = True
    schema = ResetPasswordRequestSchema

    label = _(
        "title_reset_password_request",
        default="Password recovery",
    )
    description = _(
        "description_reset_password_request",
        ("We will send you an email "
         "with the instructions to reset your password."),
    )
    button_label = _(
        "label_send_password_reminder",
        default="Send password reminder",
    )

    email_template = ViewPageTemplateFile(
        "templates/password_recovery_email.pt")

    @property
    def email_from_name(self):
        return api.portal.get_registry_record("plone.email_from_name")

    @property
    def email_from_address(self):
        return api.portal.get_registry_record("plone.email_from_address")

    def expiration_timeout(self):
        ppr = api.portal.get_tool("portal_password_reset")
        timeout = ppr.getExpirationTimeout() or 0
        return int(timeout *
                   24)  # timeout is in days, but templates want in hours.

    def log_error(self, msg):
        """Log an error message, set the view error attribute and return False"""
        logger.error(msg)
        self.error = _(
            "An error occured while sending the password reset instructions", )
        return False

    def get_remote_host(self):
        forwarded_for = self.request.get("HTTP_X_FORWARDED_FOR")
        if is_ipv4_address(forwarded_for):
            return forwarded_for
        return self.request.get("REMOTE_ADDR")

    def send_mail(self, email):
        account = Session.query(Account).filter(
            Account.loginname == email).first()
        if not account:
            # We returned True even if the account
            # does not exist to not leak any information
            return True

        ppr = api.portal.get_tool("portal_password_reset")
        # Clean out previous requests by this user
        for token, value in ppr._requests.items():
            if value[0] == account.id:
                del ppr._requests[token]
                ppr._p_changed = 1

        reset_info = ppr.requestReset(account.id)
        reset_info["host"] = self.get_remote_host()
        mailhost = api.portal.get_tool("MailHost")
        body = self.email_template(**reset_info)
        subject = translate(
            _("OiRA password reset instructions"),
            context=self.request,
        )
        mail = CreateEmailTo(
            self.email_from_name,
            self.email_from_address,
            account.email,
            subject,
            body,
        )

        try:
            mailhost.send(
                mail,
                account.email,
                self.email_from_address,
                immediate=True,
            )
            logger.info(
                "Sent password reset instructions to %s",
                account.email,
            )
        except MailHostError as e:
            msg = (
                "MailHost error sending password reset instructions to {}: {}"
            ).format(account.email, e)
            return self.log_error(msg)
        except smtplib.SMTPException as e:
            msg = (
                "smtplib error sending password reset instructions to {}: {}"
            ).format(account.email, e)
            return self.log_error(msg)
        except socket.error as e:
            msg = ("Socket error sending password reset instructions to {}: {}"
                   ).format(account.email, e[1])
            return self.log_error(msg)
        return True

    def do_next(self):
        data, error = self.extractData()
        if error:
            return
        email = data.get("email")
        if not self.send_mail(email):
            return
        msg = _(
            "message_password_recovery_email_sent",
            default="An email will be sent to ${email} "
            "if we can find an account for this email address. Please use the "
            "link inside the e-mail to reset your password.",
            mapping={"email": email},
        )
        webhelpers = api.content.get_view(name="webhelpers",
                                          context=self.context,
                                          request=self.request)
        redir_url = webhelpers.get_came_from(
            default=self.context.absolute_url())
        if not redir_url.endswith("login"):
            redir_url = "{0}/@@login?{1}#login".format(
                redir_url, urlencode({"came_from": redir_url}))
        self.redirect(redir_url, msg)

    @button.buttonAndHandler(_("Save"))
    def next_handler(self, action):
        """Check if the security token is correct and if it is
        change the account password with the provided value
        """
        self.do_next()

    @button.buttonAndHandler(_("Cancel"))
    def handleCancel(self, action):
        self.redirect(self.context.absolute_url())
示例#24
0
 def log_error(self, msg):
     """Log an error message, set the view error attribute and return False"""
     logger.error(msg)
     self.error = _(
         "An error occured while sending the password reset instructions", )
     return False
示例#25
0
 def label_start_session(self):
     label = api.portal.translate(
         _("link_start_session", default="Start a new risk assessment"))
     return capitalize(label)
示例#26
0
class TrainingView(BrowserView, survey._StatusHelper):
    """The view that shows the main-menu Training module"""

    variation_class = "variation-risk-assessment"
    skip_unanswered = False
    for_download = False
    more_menu_contents = []
    heading_measures = _("header_measures", default="Measures")
    show_slide_byline = True

    @property
    @view_memoize
    def webhelpers(self):
        return api.content.get_view("webhelpers", self.context, self.request)

    @property
    @view_memoize
    def session(self):
        """Return the session for this context/request"""
        return self.context.session

    @property
    @memoize
    def timestamp(self):
        return self.session.modified.strftime("%s%M%H%d%m")

    def get_initial_answers(self):
        """Pick a subset of questions, shuffle them, and initialize the answers with
        None.
        """
        survey = self.webhelpers._survey
        all_questions = survey.listFolderContents(
            {"portal_type": "euphorie.training_question"})
        num_training_questions = min(
            getattr(survey, "num_training_questions", None)
            or len(all_questions),
            len(all_questions),
        )
        questions = sample(all_questions, k=num_training_questions)
        return {q.getId(): None for q in questions}

    @memoize
    def get_or_create_training(self):
        """Return the training for this session"""
        account_id = self.webhelpers.get_current_account().id
        session_id = self.webhelpers.session_id
        try:
            return (Session.query(Training).filter(
                Training.session_id == session_id,
                Training.account_id == account_id).one())
        except NoResultFound:
            pass
        answers = self.get_initial_answers()
        status = "in_progress" if answers else "correct"

        training = Training(
            account_id=account_id,
            session_id=session_id,
            status=status,
            time=datetime.now(),
            answers=dumps(answers),
        )
        Session.add(training)
        return training

    @property
    @view_memoize
    def training_status(self):
        return self.get_or_create_training().status

    @property
    @view_memoize
    def question_intro_url(self):
        survey = self.webhelpers._survey
        if not getattr(survey, "enable_web_training", False):
            return ""
        view_name = "slide_question_success"
        if survey.listFolderContents(
            {"portal_type": "euphorie.training_question"
             }) and self.training_status not in ("correct", "success"):
            view_name = "slide_question_intro"
        return "{}/@@{}".format(self.context.absolute_url(), view_name)

    @property
    @view_memoize
    def question_ids(self):
        training = self.get_or_create_training()
        answer_history = loads(training.answers)
        return list(answer_history)

    @property
    def enable_training_questions(self):
        """Explicit property that can be overwritten in subpackages"""
        return bool(self.question_intro_url)

    def slicePath(self, path):
        while path:
            yield path[:3].lstrip("0")
            path = path[3:]

    @property
    @view_memoize
    def title_image(self):
        try:
            return self.context.aq_parent.external_site_logo.data
        except AttributeError:
            logger.warning(
                "Image data (logo) could not be fetched on survey  %s",
                self.context.absolute_url(),
            )
            return

    @property
    @view_memoize
    def tool_image_url(self):
        survey = self.context.aq_parent
        if getattr(survey, "image", None):
            return f"{survey.absolute_url()}/@@images/image/large"

    @property
    def logo_url(self):
        logo = self.webhelpers.get_sector_logo
        if logo:
            return f"{self.webhelpers.portal_url}/{logo.url}"
        return f"{self.webhelpers.portal_url}/++resource++euphorie.resources/media/oira-logo-colour.png"  # noqa: E501

    @property
    @view_memoize
    def slide_data(self):
        modules = self.getModulePaths()
        risks = self.getRisks(modules, skip_unanswered=self.skip_unanswered)
        seen_modules = []
        data = OrderedDict()
        for (module, risk) in risks:
            module_path = module.path
            if module_path not in seen_modules:
                module_in_context = module.__of__(
                    self.webhelpers.traversed_session)
                module_in_context.REQUEST["for_download"] = self.for_download
                _view = module_in_context.restrictedTraverse("training_slide")
                slide_contents = _view.slide_contents()
                data.update({
                    module_path: {
                        "item": module_in_context,
                        "training_view": _view,
                        "slide_contents": slide_contents,
                    }
                })
                seen_modules.append(module_path)
            risk_in_context = risk.__of__(self.webhelpers.traversed_session)
            risk_in_context.REQUEST["for_download"] = self.for_download
            _view = risk_in_context.restrictedTraverse("training_slide")
            slide_contents = _view.slide_contents()
            data.update({
                risk.path: {
                    "item": risk_in_context,
                    "training_view": _view,
                    "slide_contents": slide_contents,
                }
            })
        return data

    @property
    def slide_total_count(self):
        count = 0
        for data in self.slide_data.values():
            count += 1
            for measure_id in data["slide_contents"]["measures"]:
                if data["slide_contents"]["measures"][measure_id]["active"]:
                    count += 1
                    break
            if (data["item"].type != "module"
                    and data["slide_contents"]["training_notes"]):
                count += 1
        return count

    def handle_measure_configuration(self, reply):
        session = Session()
        risk = session.query(Risk).filter(Risk.id == reply["risk_id"]).first()
        if not risk:
            return
        # Gather all (database-) ids of the active measures. That means, those
        # measures where the checkboxes are ticked in the training configuration.
        # Remember: a measure that has been deselected (checkbox unticked)
        # does not appear in the REQUEST
        active_measures_in_place = []
        active_measures_planned = []
        for entry in reply:
            if entry.startswith(
                    "training-measure-in-place") and entry.find("-") >= 0:
                measure_id = entry.split("-")[-1]
                active_measures_in_place.append(measure_id)
            elif entry.startswith(
                    "training-measure-planned") and entry.find("-") >= 0:
                measure_id = entry.split("-")[-1]
                active_measures_planned.append(measure_id)
        # Get the (database-) ids of all measures-in-place / planned measures
        all_in_place_measures = {
            str(measure.id)
            for measure in list(risk.in_place_standard_measures) +
            list(risk.in_place_custom_measures)
        }
        all_planned_measures = {
            str(measure.id)
            for measure in list(risk.standard_measures) +
            list(risk.custom_measures)
        }
        # Additionally store the (database-) ids of all measures that have been
        # deactivated.
        deselected_in_place_measures = [
            k for k in all_in_place_measures
            if k not in active_measures_in_place
        ]
        deselected_planned_measures = [
            k for k in all_planned_measures if k not in active_measures_planned
        ]

        changed = False
        if active_measures_in_place:
            session.execute(
                "UPDATE action_plan set used_in_training=true where id in ({ids})"
                .format(  # noqa: E501
                    ids=",".join(active_measures_in_place)))
            changed = True
        if deselected_in_place_measures:
            session.execute(
                "UPDATE action_plan set used_in_training=false where id in ({ids})"
                .format(  # noqa: E501
                    ids=",".join(deselected_in_place_measures)))
            changed = True
        if active_measures_planned:
            session.execute(
                "UPDATE action_plan set used_in_training=true where id in ({ids})"
                .format(  # noqa: E501
                    ids=",".join(active_measures_planned)))
            changed = True
        if deselected_planned_measures:
            session.execute(
                "UPDATE action_plan set used_in_training=false where id in ({ids})"
                .format(  # noqa: E501
                    ids=",".join(deselected_planned_measures)))
            changed = True
        if changed:
            self.webhelpers.traversed_session.session.touch()

    def __call__(self):
        if self.webhelpers.redirectOnSurveyUpdate():
            return

        survey = self.webhelpers._survey
        utils.setLanguage(self.request, survey, survey.language)

        if self.request.environ["REQUEST_METHOD"] == "POST":
            reply = self.request.form
            if "risk_id" in reply:
                self.handle_measure_configuration(reply)

        self.request.RESPONSE.addHeader("Cache-Control", "public,max-age=60")
        return self.index()
示例#27
0
class ResetPasswordRequestSchema(model.Schema):
    email = Email(title=_("label_email", default="Email address"), )
示例#28
0
 def email_sharing_text(self):
     return api.portal.translate(
         _("I wish to share the following with you"))
示例#29
0
    def update(self):
        super(MeasuresOverview, self).update()
        lang = getattr(self.request, "LANGUAGE", "en")
        if "-" in lang:
            lang = lang.split("-")[0]
        if self.session is not None and self.session.title != (
            callable(getattr(self.context, "Title", None))
            and self.context.Title()
            or ""
        ):
            self.session_title = self.session.title
        else:
            self.session_title = (
                callable(getattr(self.context, "Title", None))
                and self.context.Title()
                or ""
            )
        today = date.today()
        this_month = date(today.year, today.month, 1)
        self.label_page = translate(
            _(u"label_page", default=u"Page"), target_language=lang
        )
        self.label_page_of = translate(
            _(u"label_page_of", default=u"of"), target_language=lang
        )

        def get_next_month(this_month):
            month = this_month.month + 1
            year = this_month.year
            if month == 13:
                month = 1
                year = year + 1
            return date(year, month, 1)

        next_month = get_next_month(this_month)
        month_after_next = get_next_month(next_month)
        self.months = []
        self.months.append(today.strftime("%b"))
        self.months.append(next_month.strftime("%b"))
        self.months.append(month_after_next.strftime("%b"))
        self.monthstrings = [
            translate(
                PloneLocalesFactory(
                    "month_{0}_abbr".format(month.lower()),
                    default=month,
                ),
                target_language=lang,
            )
            for month in self.months
        ]

        query = (
            Session.query(model.Module, model.Risk, model.ActionPlan)
            .select_from(model.Module)
            .filter(
                sql.and_(
                    model.Module.session == self.session,
                    model.Module.profile_index > -1,
                )
            )
            .filter(sql.not_(model.SKIPPED_PARENTS))
            .filter(
                sql.or_(
                    model.MODULE_WITH_RISK_OR_TOP5_FILTER,
                    model.RISK_PRESENT_OR_TOP5_FILTER,
                )
            )
            .join(model.Risk, model.Risk.parent_id == model.Module.id)
            .join(model.ActionPlan, model.ActionPlan.risk_id == model.Risk.id)
            .order_by(
                sql.case(
                    value=model.Risk.priority, whens={"high": 0, "medium": 1}, else_=2
                ),
                model.Risk.path,
            )
        )
        measures = [
            t
            for t in query.all()
            if (
                (
                    (
                        t[-1].planning_start is not None
                        and t[-1].planning_start.strftime("%b") in self.months
                    )
                    or (
                        t[-1].planning_end is not None
                        and t[-1].planning_end.strftime("%b") in self.months
                    )
                    or (
                        t[-1].planning_start is not None
                        and (
                            t[-1].planning_end is None
                            or t[-1].planning_end >= month_after_next
                        )
                        and t[-1].planning_start <= this_month
                    )
                )
                and t[1].identification not in ("n/a", "yes")
                and (
                    t[-1].responsible is not None
                    or t[-1].requirements is not None
                    or t[-1].budget is not None
                    or t[-1].action is not None
                )
            )
        ]

        modulesdict = defaultdict(lambda: defaultdict(list))
        for module, risk, action in measures:
            if "custom-risks" not in risk.zodb_path:
                risk_obj = self.survey.restrictedTraverse(risk.zodb_path.split("/"))
                title = risk_obj and risk_obj.problem_description or risk.title
            else:
                title = risk.title
            classes = []
            start_month = action.planning_start and date(
                action.planning_start.year, action.planning_start.month, 1
            )
            end_month = action.planning_end and date(
                action.planning_end.year, action.planning_end.month, 1
            )
            for m in [this_month, next_month, month_after_next]:
                cls = None
                if start_month:
                    if start_month == m:
                        cls = "start"
                    if end_month:
                        if end_month == m:
                            if end_month == (start_month is not None and start_month):
                                cls = "start-end"
                            else:
                                cls = "end"
                        elif start_month < m and end_month > m:
                            cls = "ongoing"
                    elif start_month < m:
                        cls = "ongoing"
                elif end_month:
                    if end_month == m:
                        cls = "end"
                    elif end_month > m:
                        cls = "ongoing"
                classes.append(cls)
            modulesdict[module][risk.priority].append(
                {
                    "title": title,
                    "description": action.action,
                    "months": [
                        (
                            action.planning_start
                            and action.planning_start.month == m.month
                        )
                        or (
                            action.planning_end and action.planning_end.month == m.month
                        )
                        for m in [today, next_month, month_after_next]
                    ],
                    "classes": classes,
                }
            )

        main_modules = {}
        for module, risks in sorted(modulesdict.items(), key=lambda m: m[0].zodb_path):
            module_obj = self.survey.restrictedTraverse(module.zodb_path.split("/"))
            if (
                IProfileQuestion.providedBy(module_obj)
                or ICustomRisksModule.providedBy(module_obj)
                or module.depth >= 3
            ):
                path = module.path[:6]
            else:
                path = module.path[:3]
            if path in main_modules:
                for prio in risks.keys():
                    if prio in main_modules[path]["risks"]:
                        main_modules[path]["risks"][prio].extend(risks[prio])
                    else:
                        main_modules[path]["risks"][prio] = risks[prio]
            else:
                title = module.title
                number = module.number
                main_modules[path] = {"name": title, "number": number, "risks": risks}

        self.modules = []
        for key in sorted(main_modules.keys()):
            self.modules.append(main_modules[key])
示例#30
0
 def tool_byline(self):
     title = api.portal.translate(
         _("title_tool",
           default="OiRA - Online interactive Risk Assessment"))
     return title.split("-")[-1].strip()