示例#1
0
    def _show_custom_user_attributes(self, topic):
        for name, attr in userdb.get_user_attributes():
            if topic is not None and topic != attr.topic():
                continue  # skip attrs of other topics

            vs = attr.valuespec()
            forms.section(_u(vs.title()))
            if not self._is_locked(name):
                vs.render_input("ua_" + name, self._user.get(name, vs.default_value()))
            else:
                html.write(vs.value_to_text(self._user.get(name, vs.default_value())))
                # Render hidden to have the values kept after saving
                html.open_div(style="display:none")
                vs.render_input("ua_" + name, self._user.get(name, vs.default_value()))
                html.close_div()
            html.help(_u(vs.help()))
示例#2
0
    def page(self):
        html.help(
            _("The renaming of hosts is a complex operation since a host's name is being "
              "used as a unique key in various places. It also involves stopping and starting "
              "of the monitoring core. You cannot rename a host while you have pending changes."))

        html.begin_form("rename_host", method="POST")
        forms.header(_("Rename host %s") % self._host.name())
        forms.section(_("Current name"))
        html.write_text(self._host.name())
        forms.section(_("New name"))
        html.text_input("newname", "")
        forms.end()
        html.set_focus("newname")
        html.hidden_fields()
        html.end_form()
示例#3
0
    def _activation_form(self):
        if not config.user.may("wato.activate"):
            html.show_warning(_("You are not permitted to activate configuration changes."))
            return

        if not self._changes:
            return

        if not config.user.may("wato.activateforeign") \
           and self._has_foreign_changes_on_any_site():
            html.show_warning(_("Sorry, you are not allowed to activate changes of other users."))
            return

        valuespec = _vs_activation(self.title(), self.has_foreign_changes())

        html.begin_form("activate", method="POST", action="")
        html.hidden_field("activate_until", self._get_last_change_id(), id_="activate_until")

        if valuespec:
            title = valuespec.title()
            assert title is not None
            forms.header(title)
            valuespec.render_input("activate", self._value)
            valuespec.set_focus("activate")
            html.help(valuespec.help())

        if self.has_foreign_changes():
            if config.user.may("wato.activateforeign"):
                html.show_warning(
                    _("There are some changes made by your colleagues that you will "
                      "activate if you proceed. You need to enable the checkbox above "
                      "to confirm the activation of these changes."))
            else:
                html.show_warning(
                    _("There are some changes made by your colleagues that you can not "
                      "activate because you are not permitted to. You can only activate "
                      "the changes on the sites that are not affected by these changes. "
                      "<br>"
                      "If you need to activate your changes on all sites, please contact "
                      "a permitted user to do it for you."))

        forms.end()
        html.hidden_field("selection_id", weblib.selection_id())
        html.hidden_fields()
        html.end_form()
        init_rowselect(self.name())
示例#4
0
    def _show_form(self) -> None:
        assert config.user.id is not None

        users = userdb.load_users()

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

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

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

        select_language(user)

        # Let the user configure how he wants to be notified
        rulebased_notifications = rulebased_notifications_enabled()
        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'):
            custom_user_attr_topics = get_user_attributes_by_topic()
            _show_custom_user_attr(user,
                                   custom_user_attr_topics.get("personal", []))
            forms.header(_("User interface settings"))
            _show_custom_user_attr(
                user, custom_user_attr_topics.get("interface", []))

        forms.end()
        html.close_div()
        html.hidden_fields()
        html.end_form()
        html.footer()
示例#5
0
    def render_input(self, varprefix, value):
        value = convert_cgroups_from_tuple(value)

        # If we're just editing a host, then some of the checkboxes will be missing.
        # This condition is not very clean, but there is no other way to savely determine
        # the context.
        is_host = bool(html.request.var("host")) or html.request.var("mode") == "newhost"
        is_search = varprefix == "host_search"

        # Only show contact groups I'm currently in and contact
        # groups already listed here.
        self.load_data()
        self._vs_contactgroups().render_input(varprefix + self.name(), value['groups'])

        html.hr()

        if is_host:
            html.checkbox(varprefix + self.name() + "_use",
                          value["use"],
                          label=_("Add these contact groups to the host"))

        elif not is_search:
            html.checkbox(varprefix + self.name() + "_recurse_perms",
                          value["recurse_perms"],
                          label=_("Give these groups also <b>permission on all subfolders</b>"))
            html.hr()
            html.checkbox(
                varprefix + self.name() + "_use",
                value["use"],
                label=_("Add these groups as <b>contacts</b> to all hosts in this folder"))
            html.br()
            html.checkbox(varprefix + self.name() + "_recurse_use",
                          value["recurse_use"],
                          label=_("Add these groups as <b>contacts in all subfolders</b>"))

        html.hr()
        html.help(
            _("With this option contact groups that are added to hosts are always "
              "being added to services, as well. This only makes a difference if you have "
              "assigned other contact groups to services via rules in <i>Host & Service Parameters</i>. "
              "As long as you do not have any such rule a service always inherits all contact groups "
              "from its host."))
        html.checkbox(varprefix + self.name() + "_use_for_services",
                      value.get("use_for_services", False),
                      label=_("Always add host contact groups also to its services"))
示例#6
0
    def page(self):
        new = self._folder.name() is None

        watolib.Folder.current().show_breadcrump()
        watolib.Folder.current().need_permission("read")

        if new and watolib.Folder.current().locked():
            watolib.Folder.current().show_locking_information()

        html.begin_form("edit_host", method="POST")

        # title
        forms.header(_("Title"))
        forms.section(_("Title"))
        TextUnicode().render_input("title", self._folder.title())
        html.set_focus("title")

        # folder name (omit this for root folder)
        if new or not watolib.Folder.current().is_root():
            if not config.wato_hide_filenames:
                forms.section(_("Internal directory name"))
                if new:
                    html.text_input("name")
                else:
                    html.write_text(self._folder.name())
                html.help(
                    _("This is the name of subdirectory where the files and "
                      "other folders will be created. You cannot change this later."
                      ))

        # Attributes inherited to hosts
        if new:
            parent = watolib.Folder.current()
            myself = None
        else:
            parent = watolib.Folder.current().parent()
            myself = watolib.Folder.current()

        configure_attributes(new, {"folder": myself}, "folder", parent, myself)

        forms.end()
        if new or not watolib.Folder.current().locked():
            html.button("save", _("Save & Finish"), "submit")
        html.hidden_fields()
        html.end_form()
示例#7
0
 def _show_try_form(self):
     html.begin_form('try')
     forms.header(_('Try Pattern Match'))
     forms.section(_('Hostname'))
     self._vs_host().render_input("host", self._hostname)
     forms.section(_('Logfile'))
     html.text_input('file')
     forms.section(_('Text to match'))
     html.help(
         _('You can insert some text (e.g. a line of the logfile) to test the patterns defined '
           'for this logfile. All patterns for this logfile are listed below. Matching patterns '
           'will be highlighted after clicking the "Try out" button.'))
     html.text_input('match', cssclass='match', size=100)
     forms.end()
     html.button('_try', _('Try out'))
     html.request.del_var('folder')  # Never hand over the folder here
     html.hidden_fields()
     html.end_form()
示例#8
0
文件: users.py 项目: majma24/checkmk
def select_language(user):
    languages: Choices = [
        l for l in get_languages() if not config.hide_language(l[0])
    ]
    if not languages:
        return

    current_language = user.get("language")
    if current_language is None:
        current_language = "_default_"

    languages.insert(0, ("_default_", _("Use the default language (%s)") %
                         get_language_alias(config.default_language)))

    forms.section(_("Language"))
    html.dropdown("language", languages, deflt=current_language)
    html.help(
        _('Configure the language to be used by the user in the user interface here.'
          ))
示例#9
0
 def _show_try_form(self):
     html.begin_form("try")
     forms.header(_("Try Pattern Match"))
     forms.section(_("Hostname"))
     self._vs_host().render_input("host", self._hostname)
     forms.section(_("Logfile"))
     html.help(_("Here you need to insert the original file or pathname"))
     html.text_input("file", size=80)
     forms.section(_("Text to match"))
     html.help(
         _("You can insert some text (e.g. a line of the logfile) to test the patterns defined "
           "for this logfile. All patterns for this logfile are listed below. Matching patterns "
           'will be highlighted after clicking the "Try out" button.'))
     html.text_input("match", cssclass="match", size=100)
     forms.end()
     html.button("_try", _("Try out"))
     request.del_var("folder")  # Never hand over the folder here
     html.hidden_fields()
     html.end_form()
示例#10
0
    def _select_attributes_for_bulk_cleanup(self, hosts):
        num_shown = 0
        for attr in host_attribute_registry.get_sorted_host_attributes():
            attrname = attr.name()

            if not attr.show_in_host_cleanup():
                continue

            # only show attributes that at least on host have set
            num_haveit = 0
            for host in hosts:
                if host.has_explicit_attribute(attrname):
                    num_haveit += 1

            if num_haveit == 0:
                continue

            # If the attribute is mandatory and no value is inherited
            # by file or folder, the attribute cannot be cleaned.
            container = self._folder
            is_inherited = False
            while container:
                if container.has_explicit_attribute(attrname):
                    is_inherited = True
                    break
                container = container.parent()

            num_shown += 1

            # Legend and Help
            forms.section(attr.title())

            if attr.is_mandatory() and not is_inherited:
                html.write_text(
                    _("This attribute is mandatory and there is no value "
                      "defined in the host list or any parent folder."))
            else:
                label = "clean this attribute on <b>%s</b> hosts" % \
                    (num_haveit == len(hosts) and "all selected" or str(num_haveit))
                html.checkbox("_clean_%s" % attrname, False, label=label)
            html.help(attr.help())

        return num_shown > 0
示例#11
0
    def page(self):
        html.help(
            _("This catalog of check plugins gives you a complete listing of all plugins "
              "that are shipped with your Check_MK installation. It also allows you to "
              "access the rule sets for configuring the parameters of the checks and to "
              "manually create services in case you cannot or do not want to rely on the "
              "automatic service discovery."))

        menu = MainMenu()
        for topic, _has_second_level, title, helptext in _man_page_catalog_topics():
            menu.add_item(
                MenuItem(mode_or_url=makeuri(
                    request,
                    [("mode", "check_plugin_topic"), ("topic", topic)],
                ),
                         title=title,
                         icon="plugins_" + topic,
                         permission=None,
                         description=helptext))
        menu.show()
示例#12
0
    def render(self, what):
        html.button("_acknowledge", _("Acknowledge"))
        html.button("_remove_ack", _("Remove Acknowledgement"))
        html.hr()
        html.checkbox("_ack_sticky", config.view_action_defaults["ack_sticky"], label=_("sticky"))
        html.checkbox("_ack_notify",
                      config.view_action_defaults["ack_notify"],
                      label=_("send notification"))
        html.checkbox("_ack_persistent",
                      config.view_action_defaults["ack_persistent"],
                      label=_('persistent comment'))
        html.hr()

        self._vs_expire().render_input("_ack_expire",
                                       config.view_action_defaults.get("ack_expire", 0))
        html.help(
            _("Note: Expiration of acknowledgements only works when using the Checkmk Micro Core."))
        html.hr()
        html.write_text(_("Comment") + ": ")
        html.text_input("_ack_comment", size=48, submit="_acknowledge")
示例#13
0
    def _select_attributes_for_bulk_cleanup(self, hosts):
        attributes = self._get_attributes_for_bulk_cleanup(hosts)

        for attr, is_inherited, num_haveit in attributes:
            # Legend and Help
            forms.section(attr.title())

            if attr.is_mandatory() and not is_inherited:
                html.write_text(
                    _("This attribute is mandatory and there is no value "
                      "defined in the host list or any parent folder."))
            else:
                label = "clean this attribute on <b>%s</b> hosts" % \
                    (num_haveit == len(hosts) and "all selected" or str(num_haveit))
                html.checkbox("_clean_%s" % attr.name(), False, label=label)
            html.help(attr.help())

        forms.end()

        if not attributes:
            html.write_text(_("The selected hosts have no explicit attributes"))
示例#14
0
文件: roles.py 项目: gradecke/checkmk
    def page(self):
        role_list = sorted(userdb_utils.load_roles().items(),
                           key=lambda a: (a[1]["alias"], a[0]))

        for section in permission_section_registry.get_sorted_sections():
            with table_element(
                    section.name,
                    section.title,
                    foldable=True,
            ) as table:

                permission_list = permission_registry.get_sorted_permissions(
                    section)

                if not permission_list:
                    table.row()
                    table.cell(_("Permission"), _("No entries"), css="wide")
                    continue

                for perm in permission_list:
                    table.row()
                    table.cell(_("Permission"), perm.title, css="wide")

                    html.help(perm.description)
                    for role_id, role in role_list:
                        base_on_id = role.get("basedon", role_id)
                        pvalue = role["permissions"].get(perm.name)
                        if pvalue is None:
                            if base_on_id in perm.defaults:
                                icon_name: Optional[str] = "perm_yes_default"
                            else:
                                icon_name = None
                        else:
                            icon_name = "perm_%s" % (pvalue and "yes" or "no")

                        table.cell(role_id, css="center")
                        if icon_name:
                            html.icon(icon_name)

        html.close_table()
示例#15
0
    def page(self):
        all_rulesets = watolib.AllRulesets()
        all_rulesets.load()
        for_host: bool = not self._service

        # Object type specific detail information
        if for_host:
            self._show_host_info()
        else:
            self._show_service_info(all_rulesets)

        last_maingroup = None
        for groupname in sorted(
                rulespec_group_registry.get_host_rulespec_group_names(
                    for_host)):
            maingroup = groupname.split("/")[0]
            for rulespec in sorted(rulespec_registry.get_by_group(groupname),
                                   key=lambda x: x.title or ""):
                if (rulespec.item_type == "service") == (not self._service):
                    continue  # This rule is not for hosts/services

                # Open form for that group here, if we know that we have at least one rule
                if last_maingroup != maingroup:
                    last_maingroup = maingroup
                    rulegroup = watolib.get_rulegroup(maingroup)
                    forms.header(
                        rulegroup.title,
                        isopen=maingroup == "monconf",
                        narrow=True,
                        css="rulesettings",
                    )
                    html.help(rulegroup.help)

                self._output_analysed_ruleset(all_rulesets,
                                              rulespec,
                                              svc_desc_or_item=self._service,
                                              svc_desc=self._service)

        forms.end()
示例#16
0
def select_language(user):
    languages = [
        l for l in cmk.gui.i18n.get_languages()
        if not config.hide_language(l[0])
    ]
    if languages:
        active = 'language' in user
        forms.section(_("Language"),
                      checkbox=('_set_lang', active, 'language'))
        default_label = _('Default: %s') % cmk.gui.i18n.get_language_alias(
            config.default_language)
        html.div(default_label,
                 class_="inherited",
                 id_="attr_default_language",
                 style="display: none" if active else "")
        html.open_div(id_="attr_entry_language",
                      style="display: none" if not active else "")

        language = user.get('language') if user.get(
            'language') is not None else ''

        # Transform 'en' configured language to empty string for compatibility reasons
        if language == "en":
            language = ""

        html.dropdown("language", languages, deflt=language)
        html.close_div()
        html.help(
            _('Configure the default language '
              'to be used by the user in the user interface here. If you do not check '
              'the checkbox, then the system default will be used.<br><br>'
              'Note: currently Multisite is internationalized '
              'but comes without any actual localisations (translations). If you want to '
              'create you own translation, you find <a href="%(url)s">documentation online</a>.'
              ) %
            {
                "url":
                "https://mathias-kettner.com/checkmk_multisite_cmk.gui.i18n.html"
            })
示例#17
0
文件: groups.py 项目: PLUTEX/checkmk
    def page(self) -> None:
        html.begin_form("group")
        forms.header(_("Properties"))
        forms.section(_("Name"), simple=not self._new, is_required=True)
        html.help(
            _("The name of the group is used as an internal key. It cannot be "
              "changed later. It is also visible in the status GUI."))
        if self._new:
            html.text_input("name")
            html.set_focus("name")
        else:
            html.write_text(self._name)
            html.set_focus("alias")

        forms.section(_("Alias"), is_required=True)
        html.help(_("An alias or description of this group."))
        html.text_input("alias", self.group["alias"])

        self._show_extra_page_elements()

        forms.end()
        html.hidden_fields()
        html.end_form()
示例#18
0
    def page(self):
        role_list = sorted(userdb_utils.load_roles().items(),
                           key=lambda a: (a[1]["alias"], a[0]))

        for section in permission_section_registry.get_sorted_sections():
            html.begin_foldable_container("perm_matrix",
                                          section.name,
                                          section.name == "general",
                                          section.title,
                                          indent=True)

            with table_element(section.name) as table:

                for perm in permission_registry.get_sorted_permissions(
                        section):
                    table.row()
                    table.cell(_("Permission"), perm.title, css="wide")
                    html.help(perm.description)
                    for role_id, role in role_list:
                        base_on_id = role.get('basedon', role_id)
                        pvalue = role["permissions"].get(perm.name)
                        if pvalue is None:
                            if base_on_id in perm.defaults:
                                icon_name: Optional[str] = "perm_yes_default"
                            else:
                                icon_name = None
                        else:
                            icon_name = "perm_%s" % (pvalue and "yes" or "no")

                        table.cell(role_id, css="center")
                        if icon_name:
                            html.icon(icon_name)

            html.end_foldable_container()

        html.close_table()
示例#19
0
    def page(self):
        # Let exceptions from loading notification scripts happen now
        watolib.load_notification_scripts()

        html.begin_form("user", method="POST")
        html.prevent_password_auto_completion()

        forms.header(_("Identity"))

        # ID
        forms.section(_("Username"), simple=not self._is_new_user)
        if self._is_new_user:
            vs_user_id = UserID(allow_empty=False)

        else:
            vs_user_id = FixedValue(self._user_id)
        vs_user_id.render_input("user_id", self._user_id)

        def lockable_input(name, dflt):
            if not self._is_locked(name):
                html.text_input(name, self._user.get(name, dflt), size=50)
            else:
                html.write_text(self._user.get(name, dflt))
                html.hidden_field(name, self._user.get(name, dflt))

        # Full name
        forms.section(_("Full name"))
        lockable_input('alias', self._user_id)
        html.help(_("Full name or alias of the user"))

        # Email address
        forms.section(_("Email address"))
        email = self._user.get("email", "")
        if not self._is_locked("email"):
            EmailAddressUnicode().render_input("email", email)
        else:
            html.write_text(email)
            html.hidden_field("email", email)

        html.help(
            _("The email address is optional and is needed "
              "if the user is a monitoring contact and receives notifications "
              "via Email."))

        forms.section(_("Pager address"))
        lockable_input('pager', '')
        html.help(_("The pager address is optional "))

        if cmk.is_managed_edition():
            forms.section(self._vs_customer.title())
            self._vs_customer.render_input("customer", managed.get_customer_id(self._user))

            html.help(self._vs_customer.help())

        vs_sites = self._vs_sites()
        forms.section(vs_sites.title())
        authorized_sites = self._user.get("authorized_sites", vs_sites.default_value())
        if not self._is_locked("authorized_sites"):
            vs_sites.render_input("authorized_sites", authorized_sites)
        else:
            html.write_html(vs_sites.value_to_text(authorized_sites))
        html.help(vs_sites.help())

        self._show_custom_user_attributes('ident')

        forms.header(_("Security"))
        forms.section(_("Authentication"))

        is_automation = self._user.get("automation_secret", None) is not None
        html.radiobutton("authmethod", "password", not is_automation,
                         _("Normal user login with password"))
        html.open_ul()
        html.open_table()
        html.open_tr()
        html.td(_("password:"******"_password_" + self._pw_suffix(), autocomplete="new-password")
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td(_("repeat:"))
            html.open_td()
            html.password_input("_password2_" + self._pw_suffix(), autocomplete="new-password")
            html.write_text(" (%s)" % _("optional"))
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td("%s:" % _("Enforce change"))
            html.open_td()
            # Only make password enforcement selection possible when user is allowed to change the PW
            if self._is_new_user or config.user_may(self._user_id,
                                                    'general.edit_profile') and config.user_may(
                                                        self._user_id, 'general.change_password'):
                html.checkbox("enforce_pw_change",
                              self._user.get("enforce_pw_change", False),
                              label=_("Change password at next login or access"))
            else:
                html.write_text(
                    _("Not permitted to change the password. Change can not be enforced."))
        else:
            html.i(_('The password can not be changed (It is locked by the user connector).'))
            html.hidden_field('_password', '')
            html.hidden_field('_password2', '')

        html.close_td()
        html.close_tr()
        html.close_table()
        html.close_ul()

        html.radiobutton("authmethod", "secret", is_automation,
                         _("Automation secret for machine accounts"))

        html.open_ul()
        html.text_input("_auth_secret",
                        self._user.get("automation_secret", ""),
                        size=30,
                        id_="automation_secret")
        html.write_text(" ")
        html.open_b(style=["position: relative", "top: 4px;"])
        html.write(" &nbsp;")
        html.icon_button("javascript:cmk.wato.randomize_secret('automation_secret', 20);",
                         _("Create random secret"), "random")
        html.close_b()
        html.close_ul()

        html.help(
            _("If you want the user to be able to login "
              "then specify a password here. Users without a login make sense "
              "if they are monitoring contacts that are just used for "
              "notifications. The repetition of the password is optional. "
              "<br>For accounts used by automation processes (such as fetching "
              "data from views for further procession), set the method to "
              "<u>secret</u>. The secret will be stored in a local file. Processes "
              "with read access to that file will be able to use Multisite as "
              "a webservice without any further configuration."))

        # Locking
        forms.section(_("Disable password"), simple=True)
        if not self._is_locked('locked'):
            html.checkbox("locked",
                          self._user.get("locked", False),
                          label=_("disable the login to this account"))
        else:
            html.write_text(
                _('Login disabled') if self._user.get("locked", False) else _('Login possible'))
            html.hidden_field('locked', '1' if self._user.get("locked", False) else '')
        html.help(
            _("Disabling the password will prevent a user from logging in while "
              "retaining the original password. Notifications are not affected "
              "by this setting."))

        forms.section(_("Idle timeout"))
        idle_timeout = self._user.get("idle_timeout")
        if not self._is_locked("idle_timeout"):
            watolib.get_vs_user_idle_timeout().render_input("idle_timeout", idle_timeout)
        else:
            html.write_text(idle_timeout)
            html.hidden_field("idle_timeout", idle_timeout)

        # Roles
        forms.section(_("Roles"))
        entries = self._roles.items()
        entries.sort(key=lambda x: (x[1]["alias"], x[0]))
        is_member_of_at_least_one = False
        for role_id, role in entries:
            if not self._is_locked("roles"):
                html.checkbox("role_" + role_id, role_id in self._user.get("roles", []))
                url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                html.a(role["alias"], href=url)
                html.br()
            else:
                is_member = role_id in self._user.get("roles", [])
                if is_member:
                    is_member_of_at_least_one = True
                    url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                    html.a(role["alias"], href=url)
                    html.br()

                html.hidden_field("role_" + role_id, '1' if is_member else '')
        if self._is_locked('roles') and not is_member_of_at_least_one:
            html.i(_('No roles assigned.'))
        self._show_custom_user_attributes('security')

        # Contact groups
        forms.header(_("Contact Groups"), isopen=False)
        forms.section()
        groups_page_url = watolib.folder_preserving_link([("mode", "contact_groups")])
        group_assign_url = watolib.folder_preserving_link([("mode", "rulesets"),
                                                           ("group", "grouping")])
        if not self._contact_groups:
            html.write(
                _("Please first create some <a href='%s'>contact groups</a>") % groups_page_url)
        else:
            entries = sorted([(group['alias'] or c, c) for c, group in self._contact_groups.items()
                             ])
            is_member_of_at_least_one = False
            for alias, gid in entries:
                is_member = gid in self._user.get("contactgroups", [])

                if not self._is_locked('contactgroups'):
                    html.checkbox("cg_" + gid, gid in self._user.get("contactgroups", []))
                else:
                    if is_member:
                        is_member_of_at_least_one = True
                    html.hidden_field("cg_" + gid, '1' if is_member else '')

                if not self._is_locked('contactgroups') or is_member:
                    url = watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                          ("edit", gid)])
                    html.a(alias, href=url)
                    html.br()

            if self._is_locked('contactgroups') and not is_member_of_at_least_one:
                html.i(_('No contact groups assigned.'))

        html.help(
            _("Contact groups are used to assign monitoring "
              "objects to users. If you haven't defined any contact groups yet, "
              "then first <a href='%s'>do so</a>. Hosts and services can be "
              "assigned to contact groups using <a href='%s'>rules</a>.<br><br>"
              "If you do not put the user into any contact group "
              "then no monitoring contact will be created for the user.") %
            (groups_page_url, group_assign_url))

        forms.header(_("Notifications"), isopen=False)
        if not self._rbn_enabled():
            forms.section(_("Enabling"), simple=True)
            html.checkbox("notifications_enabled",
                          self._user.get("notifications_enabled", False),
                          label=_("enable notifications"))
            html.help(
                _("Notifications are sent out "
                  "when the status of a host or service changes."))

            # Notification period
            forms.section(_("Notification time period"))
            choices = [(id_, "%s" % (tp["alias"])) for (id_, tp) in self._timeperiods.items()]
            html.dropdown("notification_period",
                          choices,
                          deflt=self._user.get("notification_period"),
                          ordered=True)
            html.help(
                _("Only during this time period the "
                  "user will get notifications about host or service alerts."))

            # Notification options
            notification_option_names = {  # defined here: _() must be executed always!
                "host": {
                    "d": _("Host goes down"),
                    "u": _("Host gets unreachble"),
                    "r": _("Host goes up again"),
                },
                "service": {
                    "w": _("Service goes into warning state"),
                    "u": _("Service goes into unknown state"),
                    "c": _("Service goes into critical state"),
                    "r": _("Service recovers to OK"),
                },
                "both": {
                    "f": _("Start or end of flapping state"),
                    "s": _("Start or end of a scheduled downtime"),
                }
            }

            forms.section(_("Notification Options"))
            for title, what, opts in [(_("Host events"), "host", "durfs"),
                                      (_("Service events"), "service", "wucrfs")]:
                html.write_text("%s:" % title)
                html.open_ul()

                user_opts = self._user.get(what + "_notification_options", opts)
                for opt in opts:
                    opt_name = notification_option_names[what].get(
                        opt, notification_option_names["both"].get(opt))
                    html.checkbox(what + "_" + opt, opt in user_opts, label=opt_name)
                    html.br()
                html.close_ul()

            html.help(
                _("Here you specify which types of alerts "
                  "will be notified to this contact. Note: these settings will only be saved "
                  "and used if the user is member of a contact group."))

            forms.section(_("Notification Method"))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", self._user.get("notification_method"))

        else:
            forms.section(_("Fallback notifications"), simple=True)

            html.checkbox("fallback_contact",
                          self._user.get("fallback_contact", False),
                          label=_("Receive fallback notifications"))

            html.help(
                _("In case none of your notification rules handles a certain event a notification "
                  "will be sent to this contact. This makes sure that in that case at least <i>someone</i> "
                  "gets notified. Furthermore this contact will be used for notifications to any host or service "
                  "that is not known to the monitoring. This can happen when you forward notifications "
                  "from the Event Console.<br><br>Notification fallback can also configured in the global "
                  "setting <a href=\"wato.py?mode=edit_configvar&varname=notification_fallback_email\">"
                  "Fallback email address for notifications</a>."))

        self._show_custom_user_attributes('notify')

        forms.header(_("Personal Settings"), isopen=False)
        select_language(self._user)
        self._show_custom_user_attributes('personal')

        # Later we could add custom macros here, which then could be used
        # for notifications. On the other hand, if we implement some check_mk
        # --notify, we could directly access the data in the account with the need
        # to store values in the monitoring core. We'll see what future brings.
        forms.end()
        html.button("save", _("Save"))
        if self._is_new_user:
            html.set_focus("user_id")
        else:
            html.set_focus("alias")
        html.hidden_fields()
        html.end_form()
示例#20
0
    def _end(self) -> None:
        if not self.rows and self.options["omit_if_empty"]:
            return

        if self.options["output_format"] == "csv":
            self._write_csv(csv_separator=html.request.get_str_input_mandatory(
                "csv_separator", ";"))
            return

        if self.title:
            if self.options["foldable"]:
                html.begin_foldable_container(
                    treename="table",
                    id_=self.id,
                    isopen=True,
                    indent=False,
                    title=html.render_h3(self.title,
                                         class_=["treeangle", "title"]))
            else:
                html.open_h3()
                html.write(self.title)
                html.close_h3()

        if self.help:
            html.help(self.help)

        if not self.rows:
            html.div(self.empty_text, class_="info")
            return

        # Controls whether or not actions are available for a table
        rows, actions_visible, search_term = self._evaluate_user_opts()

        # Apply limit after search / sorting etc.
        num_rows_unlimited = len(rows)
        limit = self.limit
        if limit is not None:
            # only use rows up to the limit plus the fixed rows
            limited_rows = []
            for index in range(num_rows_unlimited):
                row = rows[index]
                if index < limit or isinstance(row, GroupHeader) or row.fixed:
                    limited_rows.append(row)
            # Display corrected number of rows
            num_rows_unlimited -= len([
                r for r in limited_rows
                if isinstance(row, GroupHeader) or r.fixed
            ])
            rows = limited_rows

        # Render header
        if self.limit_hint is not None:
            num_rows_unlimited = self.limit_hint
        self._write_table(rows, num_rows_unlimited, self._show_action_row(),
                          actions_visible, search_term)

        if self.title and self.options["foldable"]:
            html.end_foldable_container()

        if limit is not None and num_rows_unlimited > limit:

            html.show_message(
                _('This table is limited to show only %d of %d rows. '
                  'Click <a href="%s">here</a> to disable the limitation.') %
                (limit, num_rows_unlimited, html.makeuri([('limit', 'none')])))

        return
示例#21
0
    def page(self):
        search = get_search_expression()

        html.begin_form("role", method="POST")

        # ID
        forms.header(_("Basic properties"), css="wide")
        forms.section(_("Internal ID"),
                      simple="builtin" in self._role,
                      is_required=True)
        if self._role.get("builtin"):
            html.write_text("%s (%s)" % (self._role_id, _("builtin role")))
            html.hidden_field("id", self._role_id)
        else:
            html.text_input("id", self._role_id)
            html.set_focus("id")

        # Alias
        forms.section(_("Alias"))
        html.help(_("An alias or description of the role"))
        html.text_input("alias", self._role.get("alias", ""), size=50)

        # Based on
        if not self._role.get("builtin"):
            forms.section(_("Based on role"))
            html.help(
                _("Each user defined role is based on one of the builtin roles. "
                  "When created it will start with all permissions of that role. When due to a software "
                  "update or installation of an addons new permissions appear, the user role will get or "
                  "not get those new permissions based on the default settings of the builtin role it's "
                  "based on."))
            role_choices: Choices = [(i, r["alias"])
                                     for i, r in self._roles.items()
                                     if r.get("builtin")]
            html.dropdown("basedon",
                          role_choices,
                          deflt=self._role.get("basedon", "user"),
                          ordered=True)

        forms.end()

        html.h2(_("Permissions"))

        # Permissions
        base_role_id = self._role.get("basedon", self._role_id)

        html.help(
            _("When you leave the permissions at &quot;default&quot; then they get their "
              "settings from the factory defaults (for builtin roles) or from the "
              "factory default of their base role (for user define roles). Factory defaults "
              "may change due to software updates. When choosing another base role, all "
              "permissions that are on default will reflect the new base role."
              ))

        for section in permission_section_registry.get_sorted_sections():
            # Now filter by the optional search term
            filtered_perms = []
            for perm in permission_registry.get_sorted_permissions(section):
                if search and (search not in perm.title.lower()
                               and search not in perm.name.lower()):
                    continue

                filtered_perms.append(perm)

            if not filtered_perms:
                continue

            forms.header(section.title, isopen=search is not None, css="wide")
            for perm in filtered_perms:
                forms.section(perm.title)

                pvalue = self._role["permissions"].get(perm.name)
                def_value = base_role_id in perm.defaults

                choices: Choices = [
                    ("yes", _("yes")),
                    ("no", _("no")),
                    ("default",
                     _("default (%s)") % (def_value and _("yes") or _("no"))),
                ]
                deflt = {True: "yes", False: "no"}.get(pvalue, "default")

                html.dropdown("perm_" + perm.name,
                              choices,
                              deflt=deflt,
                              style="width: 130px;")
                html.help(perm.description)

        forms.end()
        html.hidden_fields()
        html.end_form()
示例#22
0
    def _end(self) -> None:
        if not self.rows and self.options["omit_if_empty"]:
            return

        if self.options["output_format"] == "csv":
            self._write_csv(csv_separator=request.get_str_input_mandatory(
                "csv_separator", ";"))
            return

        container: ContextManager[bool] = nullcontext(False)
        if self.title:
            if self.options["foldable"] in [
                    Foldable.FOLDABLE_SAVE_STATE,
                    Foldable.FOLDABLE_STATELESS,
            ]:
                html.open_div(class_="foldable_wrapper")
                container = foldable_container(
                    treename="table",
                    id_=self.id,
                    isopen=True,
                    indent=False,
                    title=html.render_h3(self.title,
                                         class_=["treeangle", "title"]),
                    save_state=self.options["foldable"] ==
                    Foldable.FOLDABLE_SAVE_STATE,
                )
            else:
                html.h3(self.title, class_="table")

        with container:
            if self.help:
                html.help(self.help)

            if not self.rows:
                html.div(self.empty_text, class_="info")
                return

            # Controls whether or not actions are available for a table
            rows, actions_visible, search_term = self._evaluate_user_opts()

            # Apply limit after search / sorting etc.
            num_rows_unlimited = len(rows)
            limit = self.limit
            if limit:
                # only use rows up to the limit plus the fixed rows
                limited_rows = []
                for index in range(num_rows_unlimited):
                    row = rows[index]
                    if index < limit or isinstance(row,
                                                   GroupHeader) or row.fixed:
                        limited_rows.append(row)
                # Display corrected number of rows
                num_rows_unlimited -= len([
                    r for r in limited_rows
                    if isinstance(row, GroupHeader) or r.fixed
                ])
                rows = limited_rows

            # Render header
            if self.limit_hint is not None:
                num_rows_unlimited = self.limit_hint

            if limit and num_rows_unlimited > limit:

                html.show_message(
                    _("This table is limited to show only %d of %d rows. "
                      'Click <a href="%s">here</a> to disable the limitation.')
                    % (limit, num_rows_unlimited,
                       makeuri(request, [("limit", "none")])))

            self._write_table(rows, num_rows_unlimited,
                              self._show_action_row(), actions_visible,
                              search_term)

        if self.title and self.options["foldable"] in [
                Foldable.FOLDABLE_SAVE_STATE,
                Foldable.FOLDABLE_STATELESS,
        ]:
            html.close_div()

        return
示例#23
0
    def page(self):
        # Show outcome of host validation. Do not validate new hosts
        errors = None
        if self._mode != "edit":
            watolib.Folder.current().show_breadcrump()
        else:
            errors = watolib.validate_all_hosts([self._host.name()]).get(
                self._host.name(), []) + self._host.validation_errors()

        if errors:
            html.open_div(class_="info")
            html.open_table(class_="validationerror",
                            boder=0,
                            cellspacing=0,
                            cellpadding=0)
            html.open_tr()

            html.open_td(class_="img")
            html.icon(title=None, icon="validation_error")
            html.close_td()

            html.open_td()
            html.open_p()
            html.h3(_("Warning: This host has an invalid configuration!"))
            html.open_ul()
            for error in errors:
                html.li(error)
            html.close_ul()
            html.close_p()

            if html.form_submitted():
                html.br()
                html.b(_("Your changes have been saved nevertheless."))
            html.close_td()

            html.close_tr()
            html.close_table()
            html.close_div()

        lock_message = ""
        if watolib.Folder.current().locked_hosts():
            if watolib.Folder.current().locked_hosts() is True:
                lock_message = _(
                    "Host attributes locked (You cannot edit this host)")
            else:
                lock_message = watolib.Folder.current().locked_hosts()
        if len(lock_message) > 0:
            html.div(lock_message, class_="info")

        html.begin_form("edit_host", method="POST")
        html.prevent_password_auto_completion()

        forms.header(_("General Properties"))
        self._show_host_name()

        # Cluster: nodes
        if self._is_cluster():
            forms.section(_("Nodes"))
            self._vs_cluster_nodes().render_input(
                "nodes",
                self._host.cluster_nodes() if self._host else [])
            html.help(
                _('Enter the host names of the cluster nodes. These '
                  'hosts must be present in WATO. '))

        configure_attributes(
            new=self._mode != "edit",
            hosts={self._host.name(): self._host}
            if self._mode != "new" else {},
            for_what="host" if not self._is_cluster() else "cluster",
            parent=watolib.Folder.current())

        forms.end()
        if not watolib.Folder.current().locked_hosts():
            html.button("services", _("Save & go to Services"), "submit")
            html.button("save", _("Save & Finish"), "submit")
            if not self._is_cluster():
                html.button("diag_host", _("Save & Test"), "submit")
        html.hidden_fields()
        html.end_form()
示例#24
0
    def page(self):
        # TODO: remove subclass specific things specifict things (everything with _type == 'user')
        html.begin_form("attr")
        forms.header(_("Properties"))
        forms.section(_("Name"), simple=not self._new, is_required=True)
        html.help(
            _("The name of the attribute is used as an internal key. It cannot be "
              "changed later."))
        if self._new:
            html.text_input("name", self._attr.get('name', ''))
            html.set_focus("name")
        else:
            html.write_text(self._name)
            html.set_focus("title")

        forms.section(_("Title") + "<sup>*</sup>", is_required=True)
        html.help(_("The title is used to label this attribute."))
        html.text_input("title", self._attr.get('title', ''))

        forms.section(_('Topic'))
        html.help(
            _('The attribute is added to this section in the edit dialog.'))
        html.dropdown('topic',
                      self._topics,
                      deflt=self._attr.get('topic', self._default_topic))

        forms.section(_('Help Text') + "<sup>*</sup>")
        html.help(
            _('You might want to add some helpful description for the attribute.'
              ))
        html.text_area('help', self._attr.get('help', ''))

        forms.section(_('Data type'))
        html.help(_('The type of information to be stored in this attribute.'))
        if self._new:
            html.dropdown('type',
                          custom_attr_types(),
                          deflt=self._attr.get('type', ''))
        else:
            html.write(dict(custom_attr_types())[self._attr.get('type')])

        self._add_extra_form_sections()
        self._show_in_table_option()

        forms.section(_('Add to monitoring configuration'))
        html.help(self._macro_help)
        html.checkbox('add_custom_macro',
                      self._attr.get('add_custom_macro', False),
                      label=self._macro_label)

        forms.end()
        html.show_localization_hint()
        html.hidden_fields()
        html.end_form()
示例#25
0
文件: forms.py 项目: KNGP14/checkmk
def edit_dictionaries(dictionaries,
                      value,
                      focus=None,
                      hover_help=True,
                      validate=None,
                      buttontext=None,
                      title=None,
                      buttons=None,
                      method="GET",
                      preview=False,
                      varprefix="",
                      formname="form",
                      consume_transid=True):

    # Convert list of entries/dictionaries
    sections = []
    for keyname, d in dictionaries:
        if isinstance(d, list):
            sections.append((keyname, title or _("Properties"), d))
        else:
            sections.append((keyname, None,
                             d))  # valuespec Dictionary, title used from dict

    if html.request.var("filled_in") == formname and html.transaction_valid():
        if not preview and consume_transid:
            html.check_transaction()

        messages = []
        new_value = {}
        for keyname, _section_title, entries in sections:
            if isinstance(entries, list):
                new_value[keyname] = value.get(keyname, {}).copy()
                for name, vs in entries:
                    if len(sections) == 1:
                        vp = varprefix
                    else:
                        vp = keyname + "_" + varprefix
                    try:
                        v = vs.from_html_vars(vp + name)
                        vs.validate_value(v, vp + name)
                        new_value[keyname][name] = v
                    except MKUserError as e:
                        messages.append("%s: %s" % (vs.title(), e))
                        html.add_user_error(e.varname, e)

            else:
                new_value[keyname] = {}
                try:
                    edited_value = entries.from_html_vars(keyname)
                    entries.validate_value(edited_value, keyname)
                    new_value[keyname].update(edited_value)
                except MKUserError as e:
                    messages.append("%s: %s" %
                                    (entries.title() or _("Properties"), e))
                    html.add_user_error(e.varname, e)
                except Exception as e:
                    messages.append("%s: %s" %
                                    (entries.title() or _("Properties"), e))
                    html.add_user_error(None, e)

            if validate and not html.has_user_errors():
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append(e)
                    html.add_user_error(e.varname, e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, title1, entries in sections:
        subvalue = value.get(keyname, {})
        if isinstance(entries, list):
            header(title1)
            first = True
            for name, vs in entries:
                section(vs.title())
                html.help(vs.help())
                if name in subvalue:
                    v = subvalue[name]
                else:
                    v = vs.default_value()
                if len(sections) == 1:
                    vp = varprefix
                else:
                    vp = keyname + "_" + varprefix
                vs.render_input(vp + name, v)
                if (not focus and first) or (name == focus):
                    vs.set_focus(vp + name)
                    first = False
        else:
            entries.render_input_as_form(keyname, subvalue)

    end()
    if buttons:
        for name, button_title, _icon in buttons:
            html.button(name, button_title)
    else:
        if buttontext is None:
            buttontext = _("Save")
        html.button("save", buttontext)
    # Should be ignored be hidden_fields, but I do not dare to change it there
    html.request.del_var("filled_in")
    html.hidden_fields()
    html.end_form()
示例#26
0
    def _preview(self):
        # type: () -> None
        html.begin_form("preview", method="POST")
        self._preview_form()

        attributes = self._attribute_choices()

        # first line could be missing in situation of import error
        csv_reader = self._open_csv_file()
        if not csv_reader:
            return  # don't try to show preview when CSV could not be read

        html.h2(_("Preview"))
        attribute_list = "<ul>%s</ul>" % "".join(
            ["<li>%s (%s)</li>" % a for a in attributes if a[0] is not None])
        html.help(
            _("This list shows you the first 10 rows from your CSV file in the way the import is "
              "currently parsing it. If the lines are not splitted correctly or the title line is "
              "not shown as title of the table, you may change the import settings above and try "
              "again.") + "<br><br>" +
            _("The first row below the titles contains fields to specify which column of the "
              "CSV file should be imported to which attribute of the created hosts. The import "
              "progress is trying to match the columns to attributes automatically by using the "
              "titles found in the title row (if you have some). "
              "If you use the correct titles, the attributes can be mapped automatically. The "
              "currently available attributes are:") + attribute_list +
            _("You can change these assignments according to your needs and then start the "
              "import by clicking on the <i>Import</i> button above."))

        # Wenn bei einem Host ein Fehler passiert, dann wird die Fehlermeldung zu dem Host angezeigt, so dass man sehen kann, was man anpassen muss.
        # Die problematischen Zeilen sollen angezeigt werden, so dass man diese als Block in ein neues CSV-File eintragen kann und dann diese Datei
        # erneut importieren kann.
        if self._has_title_line:
            try:
                headers = list(next(csv_reader))
            except StopIteration:
                headers = []  # nope, there is no header
        else:
            headers = []

        rows = list(csv_reader)

        # Determine how many columns should be rendered by using the longest column
        num_columns = max([len(r) for r in [headers] + rows])

        with table_element(sortable=False,
                           searchable=False,
                           omit_headers=not self._has_title_line) as table:

            # Render attribute selection fields
            table.row()
            for col_num in range(num_columns):
                header = headers[col_num] if len(headers) > col_num else None
                table.cell(html.render_text(header))
                attribute_varname = "attribute_%d" % col_num
                if html.request.var(attribute_varname):
                    attribute_method = html.request.get_ascii_input_mandatory(
                        "attribute_varname")
                else:
                    attribute_method = self._try_detect_default_attribute(
                        attributes, header)
                    html.request.del_var(attribute_varname)

                html.dropdown("attribute_%d" % col_num,
                              attributes,
                              deflt=attribute_method,
                              autocomplete="off")

            # Render sample rows
            for row in rows:
                table.row()
                for cell in row:
                    table.cell(None, html.render_text(cell))

        html.end_form()
示例#27
0
    def _end(self):
        if not self.rows and self.options["omit_if_empty"]:
            return

        if self.options["output_format"] == "csv":
            self._write_csv(
                csv_separator=html.request.var("csv_separator", ";"))
            return

        if self.title:
            if self.options["foldable"]:
                html.begin_foldable_container(
                    treename="table",
                    id_=self.id,
                    isopen=True,
                    indent=False,
                    title=html.render_h3(self.title,
                                         class_=["treeangle", "title"]))
            else:
                html.open_h3()
                html.write(self.title)
                html.close_h3()

        if self.help:
            html.help(self.help)

        if not self.rows:
            html.div(self.empty_text, class_="info")
            return

        # Controls whether or not actions are available for a table
        rows, actions_enabled, actions_visible, search_term, user_opts = self._evaluate_user_opts(
        )

        # Apply limit after search / sorting etc.
        num_rows_unlimited = len(rows)
        limit = self.limit
        if limit is not None:
            # only use rows up to the limit plus the fixed rows
            rows = [
                rows[i] for i in range(num_rows_unlimited)
                if i < limit or rows[i][3]
            ]
            # Display corrected number of rows
            num_rows_unlimited -= len([r for r in rows if r[3]])

        # Render header
        self._write_table(rows, actions_enabled, actions_visible, search_term)

        if self.title and self.options["foldable"]:
            html.end_foldable_container()

        if limit is not None and num_rows_unlimited > limit:
            html.message(
                _('This table is limited to show only %d of %d rows. '
                  'Click <a href="%s">here</a> to disable the limitation.') %
                (limit, num_rows_unlimited, html.makeuri([('limit', 'none')])))

        if actions_enabled:
            config.user.save_file("tableoptions", user_opts)
        return
示例#28
0
    def page_list(cls):
        cls.load()

        # custom_columns = []
        # render_custom_buttons = None
        # render_custom_columns = None
        # render_custom_context_buttons = None
        # check_deletable_handler = None

        cls.need_overriding_permission("edit")

        html.header(cls.phrase("title_plural"))
        html.begin_context_buttons()
        html.context_button(cls.phrase("new"), cls.create_url(), "new_" + cls.type_name())

        # TODO: Remove this legacy code as soon as views, dashboards and reports have been
        # moved to pagetypes.py
        html.context_button(_("Views"), "edit_views.py", "view")
        html.context_button(_("Dashboards"), "edit_dashboards.py", "dashboard")

        def has_reporting():
            try:
                # The suppression below is OK, we just want to check if the module is there.
                import cmk.gui.cee.reporting  # noqa: F401 # pylint: disable=unused-variable,redefined-outer-name
                return True
            except ImportError:
                return False

        if has_reporting():
            html.context_button(_("Reports"), "edit_reports.py", "report")

        # ## if render_custom_context_buttons:
        # ##     render_custom_context_buttons()

        for other_type_name, other_pagetype in page_types.items():
            if cls.type_name() != other_type_name:
                html.context_button(
                    other_pagetype.phrase("title_plural").title(), '%ss.py' % other_type_name,
                    other_type_name)
        html.end_context_buttons()

        # Deletion
        delname = html.request.var("_delete")
        if delname and html.transaction_valid():
            owner = UserId(html.request.get_unicode_input_mandatory('_owner', config.user.id))

            try:
                instance = cls.instance((owner, delname))
            except KeyError:
                raise MKUserError(
                    "_delete",
                    _("The %s you are trying to delete "
                      "does not exist.") % cls.phrase("title"))

            if not instance.may_delete():
                raise MKUserError("_delete", _("You are not permitted to perform this action."))

            try:
                if owner != config.user.id:
                    owned_by = _(" (owned by %s)") % owner
                else:
                    owned_by = ""
                c = html.confirm(
                    _("Please confirm the deletion of \"%s\"%s.") % (instance.title(), owned_by))
                if c:
                    cls.remove_instance((owner, delname))
                    cls.save_user_instances(owner)
                    html.reload_sidebar()
                elif c is False:
                    html.footer()
                    return
            except MKUserError as e:
                html.user_error(e)

        # Bulk delete
        if html.request.var("_bulk_delete_my") and html.transaction_valid():
            if cls._bulk_delete_after_confirm("my") is False:
                html.footer()
                return

        elif html.request.var("_bulk_delete_foreign") and html.transaction_valid():
            if cls._bulk_delete_after_confirm("foreign") is False:
                html.footer()
                return

        my_instances, foreign_instances, builtin_instances = cls.get_instances()
        for what, title, instances in [
            ("my", _('Customized'), my_instances),
            ("foreign", _('Owned by other users'), foreign_instances),
            ("builtin", _('Builtin'), builtin_instances),
        ]:
            if not instances:
                continue

            html.open_h3()
            html.write(title)
            html.close_h3()

            if what != "builtin":
                html.begin_form("bulk_delete_%s" % what, method="POST")

            with table_element(limit=None) as table:
                for instance in instances:
                    table.row()

                    if what != "builtin" and instance.may_delete():
                        table.cell(html.render_input(
                            "_toggle_group",
                            type_="button",
                            class_="checkgroup",
                            onclick="cmk.selection.toggle_all_rows(this.form);",
                            value='X'),
                                   sortable=False,
                                   css="checkbox")
                        html.checkbox("_c_%s+%s+%s" % (what, instance.owner(), instance.name()))

                    # Actions
                    table.cell(_('Actions'), css='buttons visuals')

                    # View
                    if isinstance(instance, PageRenderer):
                        html.icon_button(instance.page_url(), _("View"), "new_" + cls.type_name())

                    # Clone / Customize
                    html.icon_button(instance.clone_url(), _("Create a customized copy of this"),
                                     "clone")

                    # Delete
                    if instance.may_delete():
                        html.icon_button(instance.delete_url(), _("Delete!"), "delete")

                    # Edit
                    if instance.may_edit():
                        html.icon_button(instance.edit_url(), _("Edit"), "edit")

                    cls.custom_list_buttons(instance)

                    # Internal ID of instance (we call that 'name')
                    table.cell(_('ID'), instance.name(), css="narrow")

                    # Title
                    table.cell(_('Title'))
                    html.write_text(instance.render_title())
                    html.help(_u(instance.description()))

                    # Custom columns specific to that page type
                    instance.render_extra_columns(table)

                    # ## for title, renderer in custom_columns:
                    # ##     table.cell(title, renderer(visual))

                    # Owner
                    if instance.is_builtin():
                        ownertxt = html.render_i(_("builtin"))
                    else:
                        ownertxt = instance.owner()
                    table.cell(_('Owner'), ownertxt)
                    table.cell(_('Public'), _("yes") if instance.is_public() else _("no"))
                    table.cell(_('Hidden'), _("yes") if instance.is_hidden() else _("no"))

                    # FIXME: WTF?!?
                    # TODO: Haeeh? Another custom columns
                    # ## if render_custom_columns:
                    # ##     render_custom_columns(visual_name, visual)

            if what != "builtin":
                html.button("_bulk_delete_%s" % what,
                            _("Bulk delete"),
                            "submit",
                            style="margin-top:10px")
                html.hidden_fields()
                html.end_form()

        html.footer()
        return
示例#29
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()
示例#30
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()