Beispiel #1
0
    def _show_form(self) -> None:
        assert user.id is not None

        credentials = load_two_factor_credentials(user.id)
        webauthn_credentials = credentials["webauthn_credentials"]
        backup_codes = credentials["backup_codes"]

        html.begin_form("two_factor", method="POST")
        html.div("", id_="webauthn_message")
        forms.header(_("Credentials"))

        forms.section(_("Registered credentials"), simple=True)
        if webauthn_credentials:
            self._show_credentials(webauthn_credentials)
        else:
            html.i(_("No credentials registered"))

        forms.section(_("Backup codes"), simple=True)
        if backup_codes:
            html.p(
                _("You have %d unused backup codes left. You can use them as one-time password "
                  "if your key is not available.") % len(backup_codes))
            html.i(
                _("If you regenerate backup codes, you automatically invalidate the existing codes."
                  ))
        else:
            html.i(_("No backup codes created yet."))

        forms.end()

        html.hidden_fields()
        html.end_form()
        html.footer()
Beispiel #2
0
    def page(self):
        host_names = get_hostnames_from_checkboxes()
        hosts = dict([
            (host_name, watolib.Folder.current().host(host_name)) for host_name in host_names
        ])
        current_host_hash = sha256(six.ensure_binary(repr(hosts)))

        # When bulk edit has been made with some hosts, then other hosts have been selected
        # and then another bulk edit has made, the attributes need to be reset before
        # rendering the form. Otherwise the second edit will have the attributes of the
        # first set.
        host_hash = html.request.var("host_hash")
        if not host_hash or host_hash != current_host_hash:
            html.request.del_vars(prefix="attr_")
            html.request.del_vars(prefix="bulk_change_")

        html.p("%s%s %s" %
               (_("You have selected <b>%d</b> hosts for bulk edit. You can now change "
                  "host attributes for all selected hosts at once. ") % len(hosts),
                _("If a select is set to <i>don't change</i> then currenty not all selected "
                  "hosts share the same setting for this attribute. "
                  "If you leave that selection, all hosts will keep their individual settings."),
                _("In case you want to <i>unset</i> attributes on multiple hosts, you need to "
                  "use the <i>bulk cleanup</i> action instead of bulk edit.")))

        html.begin_form("edit_host", method="POST")
        html.prevent_password_auto_completion()
        html.hidden_field("host_hash", current_host_hash)
        configure_attributes(False, hosts, "bulk", parent=watolib.Folder.current())
        forms.end()
        html.button("_save", _("Save & Finish"))
        html.hidden_fields()
        html.end_form()
Beispiel #3
0
def write_snapin_exception(e):
    html.open_div(class_=["snapinexception"])
    html.h2(_('Error'))
    html.p(e)
    html.div(traceback.format_exc().replace('\n', '<br>'),
             style="display:none;")
    html.close_div()
Beispiel #4
0
 def page(self):
     html.p(
         _("This module can be used to define conditions for Check_MK rules in a central place. "
           "You can then refer to these conditions from different rulesets. Using these predefined "
           "conditions may save you a lot of redundant conditions when you need them in multiple "
           "rulesets."))
     super(ModePredefinedConditions, self).page()
Beispiel #5
0
def write_snapin_exception(e: Exception) -> None:
    html.open_div(class_=["snapinexception"])
    html.h2(_("Error"))
    html.p(str(e))
    html.div(traceback.format_exc().replace("\n", "<br>"),
             style="display:none;")
    html.close_div()
Beispiel #6
0
    def page(self) -> None:
        html.h3(_("Upload Icon"))
        html.p(
            _("Allowed are single PNG image files with a maximum size of 80x80 px."
              ))

        html.begin_form('upload_form', method='POST')
        self._vs_upload().render_input('_upload_icon', None)
        html.hidden_fields()
        html.end_form()

        icons = sorted(self._load_custom_icons().items())
        with table_element("icons", _("Custom Icons")) as table:
            for icon_name, category_name in icons:
                table.row()

                table.cell(_("Actions"), css="buttons")
                delete_url = make_action_link([("mode", "icons"),
                                               ("_delete", icon_name)])
                html.icon_button(delete_url, _("Delete this Icon"), "delete")

                table.cell(_("Icon"),
                           html.render_icon(icon_name),
                           css="buttons")
                table.text_cell(_("Name"), icon_name)
                table.text_cell(_("Category"),
                                IconSelector.category_alias(category_name))
Beispiel #7
0
    def page(self) -> None:
        html.p(
            _("Here you can add icons, for example to use them in bookmarks or "
              "in custom actions of views. Allowed are single PNG image files "
              "with a maximum size of 80x80 px. Custom actions have to be defined "
              "in the global settings and can be used in the custom icons rules "
              "of hosts and services."))

        html.begin_form('upload_form', method='POST')
        self._vs_upload().render_input('_upload_icon', None)
        html.hidden_fields()
        html.end_form()

        icons = sorted(self._load_custom_icons().items())
        with table_element("icons", _("Custom Icons")) as table:
            for icon_name, category_name in icons:
                table.row()

                table.cell(_("Actions"), css="buttons")
                delete_url = make_confirm_link(
                    url=make_action_link([("mode", "icons"),
                                          ("_delete", icon_name)]),
                    message=_(
                        "Do you really want to delete the icon <b>%s</b>?") %
                    icon_name,
                )
                html.icon_button(delete_url, _("Delete this Icon"), "delete")

                table.cell(_("Icon"),
                           html.render_icon(icon_name),
                           css="buttons")
                table.cell(_("Name"), icon_name)
                table.cell(_("Category"),
                           IconSelector.category_alias(category_name))
Beispiel #8
0
    def _show_form(self, profile_changed: bool) -> None:
        assert config.user.id is not None

        users = userdb.load_users()

        change_reason = html.request.get_ascii_input('reason')

        if change_reason == 'expired':
            html.p(
                _('Your password is too old, you need to choose a new password.'
                  ))
        elif change_reason == 'enforced':
            html.p(
                _('You are required to change your password before proceeding.'
                  ))

        if profile_changed:
            html.show_message(_("Your password has been changed."))
            if change_reason:
                raise HTTPRedirect(
                    html.request.get_str_input_mandatory(
                        '_origtarget', 'index.py'))

        if html.has_user_errors():
            html.show_user_errors()

        user = users.get(config.user.id)
        if user is None:
            html.show_warning(_("Sorry, your user account does not exist."))
            html.footer()
            return

        locked_attributes = userdb.locked_attributes(user.get('connector'))
        if "password" in locked_attributes:
            raise MKUserError(
                "cur_password",
                _("You can not change your password, because it is "
                  "managed by another system."))

        html.begin_form("profile", method="POST")
        html.prevent_password_auto_completion()
        html.open_div(class_="wato")
        forms.header(self._page_title())

        forms.section(_("Current Password"))
        html.password_input('cur_password', autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input('password', autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input('password2', autocomplete="new-password")

        forms.end()
        html.close_div()
        html.hidden_fields()
        html.end_form()
        html.footer()
Beispiel #9
0
 def page(self):
     html.p(
         _("The WATO configuration can be set to read only mode for all users that are not "
           "permitted to ignore the read only mode. All users that are permitted to set the "
           "read only can disable it again when another permitted user enabled it before."))
     html.begin_form("read_only", method="POST")
     self._vs().render_input("_read_only", self._settings)
     html.hidden_fields()
     html.end_form()
Beispiel #10
0
    def show_details(self, crash_info, row):
        if not crash_info["details"]:
            return

        html.h2(_("Details"))
        html.p(
            _("No detail renderer for crash of type '%s' available. Details structure is:"
              ) % crash_info["crash_type"])
        html.pre(pprint.pformat(crash_info["details"]))
Beispiel #11
0
    def show_details(self, crash_info: CrashInfo, row) -> None:
        if not crash_info["details"]:
            return

        html.h3(_("Details"), class_="table")
        html.p(
            _("No detail renderer for crash of type '%s' available. Details structure is:"
              ) % crash_info["crash_type"])
        html.pre(pprint.pformat(crash_info["details"]))
Beispiel #12
0
    def _show_backup_codes(self, backup_codes: Sequence[str]) -> None:
        forms.header(_("Backup codes"))
        forms.section(_("Backup codes"), simple=True)
        if backup_codes:
            html.p(_("You have %d unused backup codes left.") % len(backup_codes))
            html.i(_("If you regenerate backup codes, you automatically invalidate old codes."))
        else:
            html.i(_("No backup codes created yet."))

        forms.end()
    def show(self):
        self._load()
        if not config.virtual_host_trees:
            url = 'wato.py?varname=virtual_host_trees&mode=edit_configvar'
            html.p(
                _('You have not defined any virtual host trees. You can do this '
                  'in the <a href="%s" target="main">global settings</a>.') % url)
            return

        self._show_tree_selection()
        self._show_tree()
Beispiel #14
0
    def _upload_form(self) -> None:
        html.begin_form("upload", method="POST")
        html.p(
            _("Using this page you can import several hosts at once into the choosen folder. You can "
              "choose a CSV file from your workstation to be uploaded, paste a CSV files contents "
              "into the textarea or simply enter a list of hostnames (one per line) to the textarea."
              ))

        self._vs_upload().render_input("_upload", None)
        html.hidden_fields()
        html.end_form()
Beispiel #15
0
 def page(self):
     html.p(
         _("To be able to download the key, you need to unlock the key by entering the "
           "passphrase. This is only done to verify that you are allowed to download the key. "
           "The key will be downloaded in encrypted form."))
     html.begin_form("key", method="POST")
     html.prevent_password_auto_completion()
     self._vs_key().render_input("key", {})
     self._vs_key().set_focus("key")
     html.hidden_fields()
     html.end_form()
Beispiel #16
0
 def page(self):
     html.p(
         _("This password management module stores the passwords you use in your checks and "
           "special agents in a central place. Please note that this password store is no "
           "kind of password safe. Your passwords will not be encrypted."))
     html.p(
         _("All the passwords you store in your monitoring configuration, "
           "including this password store, are needed in plain text to contact remote systems "
           "for monitoring. So all those passwords have to be stored readable by the monitoring."
           ))
     super(ModePasswords, self).page()
Beispiel #17
0
    def page(self):
        html.p(
            _('This page can be used to generate a new timeperiod definition based '
              'on the appointments of an iCalendar (<tt>*.ics</tt>) file. This import is normally used '
              'to import events like holidays, therefore only single whole day appointments are '
              'handled by this import.'))

        html.begin_form("import_ical", method="POST")
        self._vs_ical().render_input("ical", {})
        forms.end()
        html.hidden_fields()
        html.end_form()
Beispiel #18
0
def user_profile_async_replication_dialog(sites: List[SiteId], back_url: str) -> None:
    html.p(
        _(
            "In order to activate your changes available on all remote sites, your user profile needs "
            "to be replicated to the remote sites. This is done on this page now. Each site "
            "is being represented by a single image which is first shown gray and then fills "
            "to green during synchronisation."
        )
    )

    html.h3(_("Replication States"))
    html.open_div(id_="profile_repl")
    num_replsites = 0
    for site_id in sites:
        site = config.sites[site_id]
        if "secret" not in site:
            status_txt = _("Not logged in.")
            start_sync = False
            icon = "repl_locked"
        else:
            status_txt = _("Waiting for replication to start")
            start_sync = True
            icon = "repl_pending"

        html.open_div(class_="site", id_="site-%s" % site_id)
        html.div("", title=status_txt, class_=["icon", "repl_status", icon])
        if start_sync:
            changes_manager = watolib.ActivateChanges()
            changes_manager.load()
            estimated_duration = changes_manager.get_activation_time(
                site_id, ACTIVATION_TIME_PROFILE_SYNC, 2.0
            )
            html.javascript(
                "cmk.profile_replication.start(%s, %d, %s);"
                % (
                    json.dumps(site_id),
                    int(estimated_duration * 1000.0),
                    json.dumps(_("Replication in progress")),
                )
            )
            num_replsites += 1
        else:
            _add_profile_replication_change(site_id, status_txt)
        html.span(site.get("alias", site_id))

        html.close_div()

    html.javascript(
        "cmk.profile_replication.prepare(%d, %s);\n" % (num_replsites, json.dumps(back_url))
    )

    html.close_div()
Beispiel #19
0
def jqm_page_index_topic_renderer(topic: str, items: Items) -> None:
    has_items_for_topic = any(i for i in items if i[0] == topic)
    if not has_items_for_topic:
        return

    html.p(topic)
    html.open_ul(**{"data-role": "listview", "data-inset": "true"})
    for top, href, title in items:
        if top == topic:
            html.open_li()
            html.a(title, href=href, **{"data-ajax": "false", "data-transition": "flip"})
            html.close_li()
    html.close_ul()
Beispiel #20
0
    def _show_form(self) -> None:
        assert user.id is not None

        users = userdb.load_users()

        change_reason = request.get_ascii_input("reason")

        if change_reason == "expired":
            html.p(
                _("Your password is too old, you need to choose a new password."
                  ))
        elif change_reason == "enforced":
            html.p(
                _("You are required to change your password before proceeding."
                  ))

        user_spec = users.get(user.id)
        if user_spec is None:
            html.show_warning(_("Sorry, your user account does not exist."))
            html.footer()
            return

        locked_attributes = userdb.locked_attributes(
            user_spec.get("connector"))
        if "password" in locked_attributes:
            raise MKUserError(
                "cur_password",
                _("You can not change your password, because it is "
                  "managed by another system."),
            )

        html.begin_form("profile", method="POST")
        html.prevent_password_auto_completion()
        html.open_div(class_="wato")
        forms.header(self._page_title())

        forms.section(_("Current Password"))
        html.password_input("cur_password", autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input("password", autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input("password2", autocomplete="new-password")

        forms.end()
        html.close_div()
        html.hidden_fields()
        html.end_form()
        html.footer()
Beispiel #21
0
    def page(self):
        hosts = get_hosts_from_checkboxes()

        html.p(
            _("You have selected <b>%d</b> hosts for bulk cleanup. This means removing "
              "explicit attribute values from hosts. The hosts will then inherit attributes "
              "configured at the host list or folders or simply fall back to the builtin "
              "default values.") % len(hosts))

        html.begin_form("bulkcleanup", method="POST")
        forms.header(_("Attributes to remove from hosts"))
        self._select_attributes_for_bulk_cleanup(hosts)
        html.hidden_fields()
        html.end_form()
Beispiel #22
0
def render_werk_description(werk) -> HTML:
    with output_funnel.plugged():
        html.open_p()
        in_list = False
        in_code = False
        for line in werk["body"]:
            if line.startswith("LI:"):
                if not in_list:
                    html.open_ul()
                    in_list = True
                html.li(line[3:])
            else:
                if in_list:
                    html.close_ul()
                    in_list = False

                if line.startswith("H2:"):
                    html.h3(line[3:])
                elif line.startswith("C+:"):
                    html.open_pre(class_="code")
                    in_code = True
                elif line.startswith("F+:"):
                    file_name = line[3:]
                    if file_name:
                        html.div(file_name, class_="filename")
                    html.open_pre(class_="file")
                    in_code = True
                elif line.startswith("C-:") or line.startswith("F-:"):
                    html.close_pre()
                    in_code = False
                elif line.startswith("OM:"):
                    html.write_text("OMD[mysite]:~$ ")
                    html.b(line[3:])
                elif line.startswith("RP:"):
                    html.write_text("root@myhost:~# ")
                    html.b(line[3:])
                elif not line.strip() and not in_code:
                    html.p("")
                else:
                    html.write_text(line + "\n")

        if in_list:
            html.close_ul()

        html.close_p()
        return HTML(output_funnel.drain())
Beispiel #23
0
    def page(self) -> None:
        row = self._get_crash_row()
        crash_info = self._get_crash_info(row)

        title = _("Crash report: %s") % self._crash_id
        breadcrumb = self._breadcrumb(title)
        html.header(title, breadcrumb, self._page_menu(breadcrumb, crash_info))

        # Do not reveal crash context information to unauthenticated users or not permitted
        # users to prevent disclosure of internal information
        if not user.may("general.see_crash_reports"):
            html.show_error("<b>%s:</b> %s" % (_("Internal error"), crash_info["exc_value"]))
            html.p(
                _(
                    "An internal error occurred while processing your request. "
                    "You can report this issue to your Checkmk administrator. "
                    "Detailed information can be found on the crash report page "
                    "or in <tt>var/log/web.log</tt>."
                )
            )
            html.footer()
            return

        if request.has_var("_report") and transactions.check_transaction():
            details = self._handle_report_form(crash_info)
        else:
            details = ReportSubmitDetails(name="", mail="")

        if crash_info["crash_type"] == "gui":
            html.show_error("<b>%s:</b> %s" % (_("Internal error"), crash_info["exc_value"]))
            html.p(
                _(
                    "An internal error occured while processing your request. "
                    "You can report this issue to the Checkmk team to help "
                    "fixing this issue. Please use the form below for reporting."
                )
            )

        self._warn_about_local_files(crash_info)
        self._show_report_form(crash_info, details)
        self._show_crash_report(crash_info)
        self._show_crash_report_details(crash_info, row)

        html.footer()
Beispiel #24
0
def user_profile_async_replication_dialog(sites):
    html.p(
        _('In order to activate your changes available on all remote sites, your user profile needs '
          'to be replicated to the remote sites. This is done on this page now. Each site '
          'is being represented by a single image which is first shown gray and then fills '
          'to green during synchronisation.'))

    html.h3(_('Replication States'))
    html.open_div(id_="profile_repl")
    num_replsites = 0
    for site_id in sites:
        site = config.sites[site_id]
        if "secret" not in site:
            status_txt = _('Not logged in.')
            start_sync = False
            icon = 'repl_locked'
        else:
            status_txt = _('Waiting for replication to start')
            start_sync = True
            icon = 'repl_pending'

        html.open_div(class_="site", id_="site-%s" % site_id)
        html.div("", title=status_txt, class_=["icon", "repl_status", icon])
        if start_sync:
            changes_manager = watolib.ActivateChanges()
            changes_manager.load()
            estimated_duration = changes_manager.get_activation_time(
                site_id, ACTIVATION_TIME_PROFILE_SYNC, 2.0)
            html.javascript(
                'cmk.profile_replication.start(\'%s\', %d, \'%s\');' %
                (site_id, int(estimated_duration * 1000.0),
                 _('Replication in progress')))
            num_replsites += 1
        else:
            _add_profile_replication_change(site_id, status_txt)
        html.span(site.get('alias', site_id))

        html.close_div()

    html.javascript('cmk.profile_replication.prepare(%d);\n' % num_replsites)

    html.close_div()
Beispiel #25
0
def render_mobile_list(rows, view, group_cells, cells, num_columns,
                       show_checkboxes):
    if not is_mobile(request, response):
        html.show_error(_("This view can only be used in mobile mode."))
        return

    # Force relative timestamp always. This saves space.
    painter_options = PainterOptions.get_instance()
    painter_options.set("ts_format", "rel")

    html.open_ul(class_="mobilelist", **{"data-role": "listview"})

    # Paint data rows
    for row in rows:
        html.open_li()
        rendered_cells = [cell.render(row) for cell in cells]
        if rendered_cells:  # First cell (assumedly state) is left
            rendered_class, rendered_content = rendered_cells[0]
            html.p(rendered_content,
                   class_=["ui-li-aside", "ui-li-desc", rendered_class])

            if len(rendered_cells) > 1:
                content = HTML(" &middot; ").join([
                    rendered_cell[1]
                    for rendered_cell in rendered_cells[1:num_columns + 1]
                ])
                html.h3(content)

                for rendered_cell, cell in zip(
                        rendered_cells[num_columns + 1:],
                        cells[num_columns + 1:]):
                    rendered_class, rendered_content = rendered_cell
                    html.open_p(class_="ui-li-desc")
                    cell.paint_as_header()
                    html.write_text(': ')
                    html.span(rendered_content, class_=rendered_class)
                    html.close_p()

        html.close_li()
    html.close_ul()
    html.javascript('$("ul.mobilelist a").attr("data-ajax", "false");')
Beispiel #26
0
    def _show_start_form(self):
        html.begin_form("parentscan", method="POST")
        html.hidden_fields()

        # Mode of action
        html.open_p()
        if not self._complete_folder:
            num_selected = len(get_hosts_from_checkboxes())
            html.write_text(
                _("You have selected <b>%d</b> hosts for parent scan. ") %
                num_selected)
        html.p(
            _("The parent scan will try to detect the last gateway "
              "on layer 3 (IP) before a host. This will be done by "
              "calling <tt>traceroute</tt>. If a gateway is found by "
              "that way and its IP address belongs to one of your "
              "monitored hosts, that host will be used as the hosts "
              "parent. If no such host exists, an artifical ping-only "
              "gateway host will be created if you have not disabled "
              "this feature."))

        forms.header(_("Settings for Parent Scan"))

        self._settings = config.user.load_file(
            "parentscan", {
                "where": "subfolder",
                "alias": _("Created by parent scan"),
                "recurse": True,
                "select": "noexplicit",
                "timeout": 8,
                "probes": 2,
                "ping_probes": 5,
                "max_ttl": 10,
                "force_explicit": False,
            })

        # Selection
        forms.section(_("Selection"))
        if self._complete_folder:
            html.checkbox("recurse",
                          self._settings["recurse"],
                          label=_("Include all subfolders"))
            html.br()
        html.radiobutton(
            "select", "noexplicit", self._settings["select"] == "noexplicit",
            _("Skip hosts with explicit parent definitions (even if empty)") +
            "<br>")
        html.radiobutton(
            "select", "no", self._settings["select"] == "no",
            _("Skip hosts hosts with non-empty parents (also if inherited)") +
            "<br>")
        html.radiobutton("select", "ignore",
                         self._settings["select"] == "ignore",
                         _("Scan all hosts") + "<br>")

        # Performance
        forms.section(_("Performance"))
        html.open_table()
        html.open_tr()
        html.open_td()
        html.write_text(_("Timeout for responses") + ":")
        html.close_td()
        html.open_td()
        html.number_input("timeout", self._settings["timeout"], size=2)
        html.write_text(_("sec"))
        html.close_td()
        html.close_tr()

        html.open_tr()
        html.open_td()
        html.write_text(_("Number of probes per hop") + ":")
        html.close_td()
        html.open_td()
        html.number_input("probes", self._settings["probes"], size=2)
        html.close_td()
        html.close_tr()

        html.open_tr()
        html.open_td()
        html.write_text(_("Maximum distance (TTL) to gateway") + ":")
        html.close_td()
        html.open_td()
        html.number_input("max_ttl", self._settings["max_ttl"], size=2)
        html.close_td()
        html.close_tr()

        html.open_tr()
        html.open_td()
        html.write_text(_("Number of PING probes") + ":")
        html.help(
            _("After a gateway has been found, Check_MK checks if it is reachable "
              "via PING. If not, it is skipped and the next gateway nearer to the "
              "monitoring core is being tried. You can disable this check by setting "
              "the number of PING probes to 0."))
        html.close_td()
        html.open_td()
        html.number_input("ping_probes",
                          self._settings.get("ping_probes", 5),
                          size=2)
        html.close_td()
        html.close_tr()
        html.close_table()

        # Configuring parent
        forms.section(_("Configuration"))
        html.checkbox(
            "force_explicit",
            self._settings["force_explicit"],
            label=
            _("Force explicit setting for parents even if setting matches that of the folder"
              ))

        # Gateway creation
        forms.section(_("Creation of gateway hosts"))
        html.write_text(_("Create gateway hosts in"))
        html.open_ul()

        html.radiobutton(
            "where", "subfolder", self._settings["where"] == "subfolder",
            _("in the subfolder <b>%s/Parents</b>") %
            watolib.Folder.current_disk_folder().title())

        html.br()
        html.radiobutton(
            "where", "here", self._settings["where"] == "here",
            _("directly in the folder <b>%s</b>") %
            watolib.Folder.current_disk_folder().title())
        html.br()
        html.radiobutton("where", "there", self._settings["where"] == "there",
                         _("in the same folder as the host"))
        html.br()
        html.radiobutton("where", "nowhere",
                         self._settings["where"] == "nowhere",
                         _("do not create gateway hosts"))
        html.close_ul()
        html.write_text(_("Alias for created gateway hosts") + ": ")
        html.text_input("alias", self._settings["alias"])

        forms.end()

        # Start button
        html.button("_start", _("Start"))
        html.hidden_fields()
        html.end_form()
Beispiel #27
0
def page_crashed(what):
    # Do not reveal crash context information to unauthenticated users or not permitted
    # users to prevent disclosure of internal information
    if not config.user.may("general.see_crash_reports"):
        html.header(_("Internal error"))
        html.show_error("<b>%s:</b> %s" %
                        (_("Internal error"), sys.exc_info()[1]))
        html.p(
            _("An internal error occurred while processing your request. "
              "You can report this issue to your Check_MK administrator. "
              "Detailed information can be found in <tt>var/log/web.log</tt>.")
        )
        html.footer()
        return

    if what == "check":
        site = html.request.var("site")
        host = html.request.var("host")
        service = html.request.var("service")

        tardata = get_crash_report_archive_as_string(site, host, service)
    else:
        tardata = create_gui_crash_report(what)

    info = get_crash_info(tardata)

    if what == "check":
        title = _("Crashed Check Reporting")
    else:
        title = _("Internal error")

    html.header(title)

    show_context_buttons(what, tardata)

    if html.request.has_var("_report") and html.check_transaction():
        details = handle_report_form(tardata, what)
    else:
        details = {}

    if what == "gui":
        # Unify different string types from exception messages to a unicode string
        exc_value = sys.exc_info()[1]
        try:
            exc_txt = unicode(exc_value)
        except UnicodeDecodeError:
            exc_txt = str(exc_value).decode("utf-8")

        html.show_error("<b>%s:</b> %s" % (_("Internal error"), exc_txt))
        html.p(
            _("An internal error occured while processing your request. "
              "You can report this issue to the Check_MK team to help "
              "fixing this issue. Please use the form below for reporting."))

    if info:
        warn_about_local_files(info)
        show_report_form(what, details)
        show_crash_report(info)
        show_crash_report_details(info)
    else:
        report_url = html.makeuri(
            [("subject", "Check_MK Crash Report - " + get_version(what))],
            filename="mailto:" + get_crash_report_target(what))
        html.message(
            _("This crash report is in a legacy format and can not be submitted "
              "automatically. Please download it manually and send it to <a href=\"%s\">%s</a>"
              ) % (report_url, get_crash_report_target(what)))
        show_old_dump_trace(tardata)

    show_agent_output(tardata)

    html.footer()
Beispiel #28
0
def _show_page_user_profile(change_pw):
    start_async_replication = False

    if not config.user.id:
        raise MKUserError(None, _('Not logged in.'))

    if not config.user.may('general.edit_profile') and not config.user.may(
            'general.change_password'):
        raise MKAuthException(
            _("You are not allowed to edit your user profile."))

    if not config.wato_enabled:
        raise MKAuthException(
            _('User profiles can not be edited (WATO is disabled).'))

    success = None
    if html.request.has_var('_save') and html.check_transaction():
        users = userdb.load_users(lock=True)

        try:
            # Profile edit (user options like language etc.)
            if config.user.may('general.edit_profile'):
                if not change_pw:
                    set_lang = html.get_checkbox('_set_lang')
                    language = html.request.var('language')
                    # Set the users language if requested
                    if set_lang:
                        if language == '':
                            language = None
                        # Set custom language
                        users[config.user.id]['language'] = language
                        config.user.language = language
                        html.set_language_cookie(language)

                    else:
                        # Remove the customized language
                        if 'language' in users[config.user.id]:
                            del users[config.user.id]['language']
                        config.user.reset_language()

                    # load the new language
                    cmk.gui.i18n.localize(config.user.language)

                    user = users.get(config.user.id)
                    if config.user.may('general.edit_notifications'
                                       ) and user.get("notifications_enabled"):
                        value = forms.get_input(
                            watolib.get_vs_flexible_notifications(),
                            "notification_method")
                        users[config.user.id]["notification_method"] = value

                    # Custom attributes
                    if config.user.may('general.edit_user_attributes'):
                        for name, attr in userdb.get_user_attributes():
                            if attr.user_editable():
                                if not attr.permission() or config.user.may(
                                        attr.permission()):
                                    vs = attr.valuespec()
                                    value = vs.from_html_vars('ua_' + name)
                                    vs.validate_value(value, "ua_" + name)
                                    users[config.user.id][name] = value

            # Change the password if requested
            password_changed = False
            if config.user.may('general.change_password'):
                cur_password = html.request.var('cur_password')
                password = html.request.var('password')
                password2 = html.request.var('password2', '')

                if change_pw:
                    # Force change pw mode
                    if not cur_password:
                        raise MKUserError(
                            "cur_password",
                            _("You need to provide your current password."))
                    if not password:
                        raise MKUserError(
                            "password", _("You need to change your password."))
                    if cur_password == password:
                        raise MKUserError(
                            "password",
                            _("The new password must differ from your current one."
                              ))

                if cur_password and password:
                    if userdb.hook_login(config.user.id,
                                         cur_password) is False:
                        raise MKUserError("cur_password",
                                          _("Your old password is wrong."))
                    if password2 and password != password2:
                        raise MKUserError(
                            "password2",
                            _("The both new passwords do not match."))

                    watolib.verify_password_policy(password)
                    users[config.user.id]['password'] = hash_password(password)
                    users[config.user.id]['last_pw_change'] = int(time.time())

                    if change_pw:
                        # Has been changed, remove enforcement flag
                        del users[config.user.id]['enforce_pw_change']

                    # Increase serial to invalidate old cookies
                    if 'serial' not in users[config.user.id]:
                        users[config.user.id]['serial'] = 1
                    else:
                        users[config.user.id]['serial'] += 1

                    password_changed = True

            # Now, if in distributed environment where users can login to remote sites,
            # set the trigger for pushing the new auth information to the slave sites
            # asynchronous
            if config.user.authorized_login_sites():
                start_async_replication = True

            userdb.save_users(users)

            if password_changed:
                # Set the new cookie to prevent logout for the current user
                login.set_auth_cookie(config.user.id)

            success = True
        except MKUserError as e:
            html.add_user_error(e.varname, e)
    else:
        users = userdb.load_users()

    watolib.init_wato_datastructures(with_wato_lock=True)

    # When in distributed setup, display the replication dialog instead of the normal
    # profile edit dialog after changing the password.
    if start_async_replication:
        user_profile_async_replication_page()
        return

    if change_pw:
        title = _("Change Password")
    else:
        title = _("Edit User Profile")

    html.header(title)

    # Rule based notifications: The user currently cannot simply call the according
    # WATO module due to WATO permission issues. So we cannot show this button
    # right now.
    if not change_pw:
        rulebased_notifications = watolib.load_configuration_settings().get(
            "enable_rulebased_notifications")
        if rulebased_notifications and config.user.may(
                'general.edit_notifications'):
            html.begin_context_buttons()
            url = "wato.py?mode=user_notifications_p"
            html.context_button(_("Notifications"), url, "notifications")
            html.end_context_buttons()
    else:
        reason = html.request.var('reason')
        if reason == 'expired':
            html.p(
                _('Your password is too old, you need to choose a new password.'
                  ))
        else:
            html.p(
                _('You are required to change your password before proceeding.'
                  ))

    if success:
        html.reload_sidebar()
        if change_pw:
            html.show_message(_("Your password has been changed."))
            raise HTTPRedirect(html.request.var('_origtarget', 'index.py'))
        else:
            html.show_message(_("Successfully updated user profile."))
            # Ensure theme changes are applied without additional user interaction
            html.immediate_browser_redirect(0.5, html.makeuri([]))

    if html.has_user_errors():
        html.show_user_errors()

    user = users.get(config.user.id)
    if user is None:
        html.show_warning(_("Sorry, your user account does not exist."))
        html.footer()
        return

    # Returns true if an attribute is locked and should be read only. Is only
    # checked when modifying an existing user
    locked_attributes = userdb.locked_attributes(user.get('connector'))

    def is_locked(attr):
        return attr in locked_attributes

    html.begin_form("profile", method="POST")
    html.prevent_password_auto_completion()
    html.open_div(class_="wato")
    forms.header(_("Personal Settings"))

    if not change_pw:
        forms.section(_("Name"), simple=True)
        html.write_text(user.get("alias", config.user.id))

    if config.user.may(
            'general.change_password') and not is_locked('password'):
        forms.section(_("Current Password"))
        html.password_input('cur_password', autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input('password', autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input('password2', autocomplete="new-password")

    if not change_pw and config.user.may('general.edit_profile'):
        select_language(user)

        # Let the user configure how he wants to be notified
        if not rulebased_notifications \
            and config.user.may('general.edit_notifications') \
            and user.get("notifications_enabled"):
            forms.section(_("Notifications"))
            html.help(
                _("Here you can configure how you want to be notified about host and service problems and "
                  "other monitoring events."))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", user.get("notification_method"))

        if config.user.may('general.edit_user_attributes'):
            for name, attr in userdb.get_user_attributes():
                if attr.user_editable():
                    vs = attr.valuespec()
                    forms.section(_u(vs.title()))
                    value = user.get(name, vs.default_value())
                    if not attr.permission() or config.user.may(
                            attr.permission()):
                        vs.render_input("ua_" + name, value)
                        html.help(_u(vs.help()))
                    else:
                        html.write(vs.value_to_text(value))

    # Save button
    forms.end()
    html.button("_save", _("Save"))
    html.close_div()
    html.hidden_fields()
    html.end_form()
    html.footer()