Пример #1
0
def _validate_general_host_attributes(host_attributes, new):
    # inventory_failed and site are no "real" host_attributes (TODO: Clean this up!)
    all_host_attribute_names = host_attribute_registry.keys() + [
        "inventory_failed", "site"
    ]
    for name, value in host_attributes.items():
        if name not in all_host_attribute_names:
            raise MKUserError(
                None,
                _("Unknown attribute: %s") % html.attrencode(name))

        # For real host attributes validate the values
        try:
            attr = watolib.host_attribute(name)
        except KeyError:
            attr = None

        if attr is not None:
            if attr.needs_validation("host", new):
                attr.validate_input(value, "")

        # The site attribute gets an extra check
        if name == "site" and value not in config.allsites().keys():
            raise MKUserError(None,
                              _("Unknown site %s") % html.attrencode(value))
Пример #2
0
 def _render_warnings(self, configuration_warnings):
     html_code = "<div class=warning>"
     html_code += "<b>%s</b>" % _("Warnings:")
     html_code += "<ul>"
     for domain, warnings in sorted(configuration_warnings.items()):
         for warning in warnings:
             html_code += "<li>%s: %s</li>" % \
                 (html.attrencode(domain), html.attrencode(warning))
     html_code += "</ul>"
     html_code += "</div>"
     return html_code
Пример #3
0
def _validate_host_tags(host_tags):
    for tag_group_id, tag_id in host_tags.items():
        for tag_group in config.tags.tag_groups:
            if tag_group.id == tag_group_id:
                for grouped_tag in tag_group.tags:
                    if grouped_tag.id == tag_id:
                        break
                else:
                    raise MKUserError(None, _("Unknown tag %s") % html.attrencode(tag_id))
                break
        else:
            raise MKUserError(None, _("Unknown tag group %s") % html.attrencode(tag_group_id))
Пример #4
0
    def _show_row_cells(self, table, name, group):
        table.cell(_("Actions"), css="buttons")
        edit_url = watolib.folder_preserving_link([("mode", "edit_%s_group" % self.type_name),
                                                   ("edit", name)])
        delete_url = html.makeactionuri([("_delete", name)])
        clone_url = watolib.folder_preserving_link([("mode", "edit_%s_group" % self.type_name),
                                                    ("clone", name)])
        html.icon_button(edit_url, _("Properties"), "edit")
        html.icon_button(clone_url, _("Create a copy of this group"), "clone")
        html.icon_button(delete_url, _("Delete"), "delete")

        table.cell(_("Name"), html.attrencode(name))
        table.cell(_("Alias"), html.attrencode(group['alias']))
Пример #5
0
def page_index():
    html.write(
        '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">\n'
        '<html><head>\n')
    html.default_html_headers()
    html.write("""<title>%s</title>
</head>
<frameset cols="280,*" frameborder="0" framespacing="0" border="0">
    <frame src="side.py" name="side" noresize scrolling="no">
    <frame src="%s" name="main" noresize>
</frameset>
</html>
""" % (html.attrencode(
        config.get_page_heading()), html.attrencode(_get_start_url())))
Пример #6
0
def log_entry(linkinfo, action, message, user_id=None):
    # Using attrencode here is against our regular rule to do the escaping
    # at the last possible time: When rendering. But this here is the last
    # place where we can distinguish between HTML() encapsulated (already)
    # escaped / allowed HTML and strings to be escaped.
    message = html.attrencode(message).strip()

    # TODO: Create a more generic referencing
    # linkinfo identifies the object operated on. It can be a Host or a Folder
    # or a text.
    # linkinfo is either a Folder, or a Host or a hostname or None
    if hasattr(linkinfo, "linkinfo"):
        link = linkinfo.linkinfo()
    else:
        link = linkinfo

    write_tokens = (
        time.strftime("%s"),
        link or "-",
        user_id or config.user.id or "-",
        action,
        message.replace("\n", "\\n"),
    )

    # TODO: once we know all of these are unicode, remove this line
    write_tokens = (t if isinstance(t, unicode) else t.encode("utf-8")
                    for t in write_tokens)

    store.makedirs(audit_log_path.parent)
    with audit_log_path.open(mode="a", encoding='utf-8') as f:
        audit_log_path.chmod(0o660)
        f.write(u" ".join(write_tokens) + u"\n")
Пример #7
0
def page_login():
    title = _("Check_MK Mobile")
    mobile_html_head(title)
    jqm_page_header(title, id_="login")
    html.div(_("Welcome to Check_MK Mobile."), id_="loginhead")

    html.begin_form("login", method='POST', add_transid=False)
    # Keep information about original target URL
    origtarget = html.request.var('_origtarget', '')
    if not origtarget and not html.myfile == 'login':
        origtarget = html.request.requested_url
    html.hidden_field('_origtarget', html.attrencode(origtarget))

    html.text_input("_username", label=_("Username:"******"_password", size=None, label=_("Password:"******"_login", _('Login'))
    html.set_focus("_username")
    html.end_form()
    html.open_div(id_="loginfoot")
    html.img("themes/classic/images/logo_cmk_small.png", class_="logomk")
    html.div(HTML(
        _("&copy; <a target=\"_blank\" href=\"https://checkmk.com\">tribe29 GmbH</a>"
          )),
             class_="copyright")
    jqm_page_footer()
    mobile_html_foot()
Пример #8
0
def page_login():
    title = _("Check_MK Mobile")
    mobile_html_head(title)
    jqm_page_header(title, id_="login")
    html.div(_("Welcome to Check_MK Mobile."), id_="loginhead")

    html.begin_form("login", method='POST', add_transid=False)
    # Keep information about original target URL
    default_origtarget = "index.py" if html.myfile in ["login", "logout"] else html.makeuri([])
    origtarget = html.get_url_input("_origtarget", default_origtarget)
    html.hidden_field('_origtarget', html.attrencode(origtarget))

    html.text_input("_username", label=_("Username:"******"username")
    html.password_input("_password",
                        size=None,
                        label=_("Password:"******"current-password")
    html.br()
    html.button("_login", _('Login'))
    html.set_focus("_username")
    html.end_form()
    html.open_div(id_="loginfoot")
    html.img("themes/classic/images/logo_cmk_small.png", class_="logomk")
    html.div(HTML(_("&copy; <a target=\"_blank\" href=\"https://checkmk.com\">tribe29 GmbH</a>")),
             class_="copyright")
    html.close_div()  # close content-div
    html.close_div()
    html.close_div()  # close page-div
    mobile_html_foot()
Пример #9
0
    def _add_change_to_site(self, site_id, change_id, action_name, text, obj, add_user, need_sync,
                            need_restart, domains):
        # Individual changes may override the domain restart default value
        if need_restart is None:
            need_restart = any([d.needs_activation for d in domains])

        if need_sync is None:
            need_sync = any([d.needs_sync for d in domains])

        def serialize_object(obj):
            if obj is None:
                return None
            return obj.__class__.__name__, obj.ident()

        # Using attrencode here is against our regular rule to do the escaping
        # at the last possible time: When rendering. But this here is the last
        # place where we can distinguish between HTML() encapsulated (already)
        # escaped / allowed HTML and strings to be escaped.
        text = html.attrencode(text)

        SiteChanges(site_id).save_change({
            "id": change_id,
            "action_name": action_name,
            "text": "%s" % text,
            "object": serialize_object(obj),
            "user_id": config.user.id if add_user else None,
            "domains": [d.ident for d in domains],
            "time": time.time(),
            "need_sync": need_sync,
            "need_restart": need_restart,
        })
Пример #10
0
def page_view():
    view_name = html.request.var("view_name")
    if not view_name:
        return page_index()

    view_spec = views.get_permitted_views().get(view_name)
    if not view_spec:
        raise MKUserError("view_name",
                          "No view defined with the name '%s'." % view_name)

    view = views.View(view_name, view_spec)
    view.row_limit = views.get_limit()
    view.only_sites = views.get_only_sites()
    view.user_sorters = views.get_user_sorters()

    title = views.view_title(view_spec)
    mobile_html_head(title)

    painter_options = PainterOptions.get_instance()
    painter_options.load(view_name)

    try:
        view_renderer = MobileViewRenderer(view)
        views.show_view(view, view_renderer)
    except Exception as e:
        logger.exception()
        if config.debug:
            raise
        html.write("ERROR showing view: %s" % html.attrencode(e))

    mobile_html_foot()
Пример #11
0
def _get_api_call():
    action = html.request.var('action')
    for cls in api_call_collection_registry.values():
        api_call = cls().get_api_calls().get(action)
        if api_call:
            return api_call
    raise MKUserError(None, "Unknown API action %s" % html.attrencode(action))
Пример #12
0
def log_entry(linkinfo, action, message, user_id=None):
    # Using attrencode here is against our regular rule to do the escaping
    # at the last possible time: When rendering. But this here is the last
    # place where we can distinguish between HTML() encapsulated (already)
    # escaped / allowed HTML and strings to be escaped.
    message = cmk.utils.make_utf8(html.attrencode(message)).strip()

    # TODO: Create a more generic referencing
    # linkinfo identifies the object operated on. It can be a Host or a Folder
    # or a text.
    # linkinfo is either a Folder, or a Host or a hostname or None
    if hasattr(linkinfo, "linkinfo"):
        link = linkinfo.linkinfo()
    elif linkinfo is None:
        link = "-"
    else:
        link = linkinfo

    if user_id is None and config.user.id is not None:
        user_id = config.user.id
    elif user_id == '':
        user_id = '-'

    if user_id:
        user_id = user_id.encode("utf-8")

    store.makedirs(os.path.dirname(audit_log_path))
    with open(audit_log_path, "ab") as f:
        os.chmod(f.name, 0o660)
        f.write("%d %s %s %s %s\n" % (int(
            time.time()), link, user_id, action, message.replace("\n", "\\n")))
Пример #13
0
    def run(self):
        self._executed = True
        try:
            # Do not merge results that have been gathered on one site for different sites
            results = list(self.execute())
            num_sites = len(set(r.site_id for r in results))
            if num_sites > 1:
                for result in results:
                    result.from_test(self)
                    yield result
                return

            # Merge multiple results produced for a single site
            total_result = ACResult.merge(*list(self.execute()))
            total_result.from_test(self)
            yield total_result
        except Exception:
            logger.exception("error executing configuration test %s",
                             self.__class__.__name__)
            result = ACResultCRIT(
                "<pre>%s</pre>" % _("Failed to execute the test %s: %s") %
                (html.attrencode(
                    self.__class__.__name__), traceback.format_exc()))
            result.from_test(self)
            yield result
Пример #14
0
def show_crash_report(info):

    html.h2(_("Crash Report"))
    html.open_table(class_="data")

    _crash_row(_("Crash Type"), info["crash_type"], odd=False, legend=True)
    _crash_row(
        _("Time"), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(info["time"])), odd=True)
    _crash_row(_("Operating System"), info["os"], False)
    if info["crash_type"] == "cma":
        version_title = _("CMA Version")
    else:
        version_title = _("Check_MK Version")
    _crash_row(version_title, info["version"], True)
    _crash_row(_("Edition"), info.get("edition", ""), False)
    _crash_row(_("Core"), info.get("core", ""), True)
    _crash_row(_("Python Version"), info.get("python_version", _("Unknown")), False)
    _crash_row(
        _("Exception"), "%s (%s)" % (info["exc_type"], info["exc_value"]), odd=True, pre=True)
    _crash_row(_("Traceback"), format_traceback(info["exc_traceback"]), odd=False, pre=True)
    _crash_row(
        _("Local Variables"),
        format_local_vars(info["local_vars"]) if "local_vars" in info else "",
        odd=True,
        pre=True)

    joined_paths = "<br>".join(
        [html.attrencode(p) for p in info.get("python_paths", [_("Unknown")])])
    _crash_row(_("Python Module Paths"), joined_paths, odd=False)

    html.close_table()
Пример #15
0
 def action(self, cmdtag, spec, row, row_index, num_rows):
     for s in [0, 1, 2, 3]:
         statename = html.request.var("_fake_%d" % s)
         if statename:
             pluginoutput = html.get_unicode_input("_fake_output").strip()
             if not pluginoutput:
                 pluginoutput = _("Manually set to %s by %s") % (
                     html.attrencode(statename), config.user.id)
             perfdata = html.request.var("_fake_perfdata")
             if perfdata:
                 pluginoutput += "|" + perfdata
             if cmdtag == "SVC":
                 cmdtag = "SERVICE"
             command = "PROCESS_%s_CHECK_RESULT;%s;%s;%s" % (
                 cmdtag, spec, s, livestatus.lqencode(pluginoutput))
             title = _("<b>manually set check results to %s</b> for"
                       ) % html.attrencode(statename)
             return command, title
Пример #16
0
 def render_messages(self):
     for msg in notify.get_gui_messages():
         if 'gui_hint' in msg['methods']:
             html.open_div(id_="message-%s" % msg['id'], class_=["popup_msg"])
             html.a("x",
                    href="javascript:void(0)",
                    class_=["close"],
                    onclick="cmk.sidebar.message_close(\'%s\')" % msg['id'])
             html.write_text(msg['text'].replace('\n', '<br>\n'))
             html.close_div()
         if 'gui_popup' in msg['methods']:
             html.javascript('alert(\'%s\'); cmk.sidebar.mark_message_read("%s")' %
                             (html.attrencode(msg['text']).replace('\n', '\\n'), msg['id']))
Пример #17
0
    def _activate_changes(self, request):
        mode = request.get("mode", "dirty")
        if request.get("allow_foreign_changes"):
            allow_foreign_changes = bool(
                int(request.get("allow_foreign_changes")))
        else:
            allow_foreign_changes = False

        sites = request.get("sites")

        changes = watolib.ActivateChanges()
        changes.load()

        if changes.has_foreign_changes():
            if not config.user.may("wato.activateforeign"):
                raise MKAuthException(
                    _("You are not allowed to activate changes of other users."
                      ))
            if not allow_foreign_changes:
                raise MKAuthException(_("There are changes from other users and foreign changes "\
                                        "are not allowed in this API call."))

        if mode == "specific":
            for site in sites:
                if site not in config.allsites().keys():
                    raise MKUserError(
                        None,
                        _("Unknown site %s") % html.attrencode(site))

        manager = watolib.ActivateChangesManager()
        manager.load()

        if not manager.has_changes():
            raise MKUserError(None,
                              _("Currently there are no changes to activate."))

        if not sites:
            sites = manager.dirty_and_active_activation_sites()

        comment = request.get("comment", "").strip()
        if comment == "":
            comment = None

        manager.start(sites,
                      comment=comment,
                      activate_foreign=allow_foreign_changes)
        manager.wait_for_completion()
        return manager.get_state()
Пример #18
0
def format_plugin_output(output, row=None, shall_escape=True):
    ok_marker = '<b class="stmark state0">OK</b>'
    warn_marker = '<b class="stmark state1">WARN</b>'
    crit_marker = '<b class="stmark state2">CRIT</b>'
    unknown_marker = '<b class="stmark state3">UNKN</b>'

    # In case we have a host or service row use the optional custom attribute
    # ESCAPE_PLUGIN_OUTPUT (set by host / service ruleset) to override the global
    # setting.
    if row:
        custom_vars = row.get("service_custom_variables",
                              row.get("host_custom_variables", {}))
        if "ESCAPE_PLUGIN_OUTPUT" in custom_vars:
            shall_escape = custom_vars["ESCAPE_PLUGIN_OUTPUT"] == "1"

    if shall_escape:
        output = html.attrencode(output)

    output = output.replace("(!)", warn_marker) \
              .replace("(!!)", crit_marker) \
              .replace("(?)", unknown_marker) \
              .replace("(.)", ok_marker)

    if row and "[running on" in output:
        a = output.index("[running on")
        e = output.index("]", a)
        hosts = output[a + 12:e].replace(" ", "").split(",")
        h = get_host_list_links(row["site"], hosts)
        output = output[:a] + "running on " + ", ".join(h) + output[e + 1:]

    if shall_escape:
        http_url = r"(http[s]?://[A-Za-z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+)"
        # (?:&lt;A HREF=&quot;), (?: target=&quot;_blank&quot;&gt;)? and endswith(" </A>") is a special
        # handling for the HTML code produced by check_http when "clickable URL" option is active.
        output = re.sub(
            "(?:&lt;A HREF=&quot;)?" + http_url +
            "(?: target=&quot;_blank&quot;&gt;)?", lambda p: str(
                html.render_icon_button(
                    p.group(1).replace('&quot;', ''),
                    p.group(1).replace('&quot;', ''), "link")), output)

        if output.endswith(" &lt;/A&gt;"):
            output = output[:-11]

    return output
Пример #19
0
    def _push_snapshot_to_site(self):
        """Calls a remote automation call push-snapshot which is handled by AutomationPushSnapshot()"""
        site = config.site(self._site_id)

        url = html.makeuri_contextless(
            [
                ("command", "push-snapshot"),
                ("secret", site["secret"]),
                ("siteid", site["id"]),
                ("debug", config.debug and "1" or ""),
            ],
            filename=site["multisiteurl"] + "automation.py",
        )

        response_text = self._upload_file(url, site.get('insecure', False))

        try:
            return ast.literal_eval(response_text)
        except SyntaxError:
            raise cmk.gui.watolib.automations.MKAutomationException(
                _("Garbled automation response: <pre>%s</pre>") % (html.attrencode(response_text)))
Пример #20
0
    def _ajax_switch_masterstate(self):
        html.set_output_format("text")

        if not config.user.may("sidesnap.master_control"):
            return

        if not html.check_transaction():
            return

        site = html.request.var("site")
        column = html.request.var("switch")
        state = int(html.request.var("state"))
        commands = {
            ("enable_notifications", 1): "ENABLE_NOTIFICATIONS",
            ("enable_notifications", 0): "DISABLE_NOTIFICATIONS",
            ("execute_service_checks", 1): "START_EXECUTING_SVC_CHECKS",
            ("execute_service_checks", 0): "STOP_EXECUTING_SVC_CHECKS",
            ("execute_host_checks", 1): "START_EXECUTING_HOST_CHECKS",
            ("execute_host_checks", 0): "STOP_EXECUTING_HOST_CHECKS",
            ("enable_flap_detection", 1): "ENABLE_FLAP_DETECTION",
            ("enable_flap_detection", 0): "DISABLE_FLAP_DETECTION",
            ("process_performance_data", 1): "ENABLE_PERFORMANCE_DATA",
            ("process_performance_data", 0): "DISABLE_PERFORMANCE_DATA",
            ("enable_event_handlers", 1): "ENABLE_EVENT_HANDLERS",
            ("enable_event_handlers", 0): "DISABLE_EVENT_HANDLERS",
        }

        command = commands.get((column, state))
        if command:
            sites.live().command("[%d] %s" % (int(time.time()), command), site)
            sites.live().set_only_sites([site])
            sites.live().query("GET status\nWaitTrigger: program\nWaitTimeout: 10000\nWaitCondition: %s = %d\nColumns: %s\n" % \
                   (column, state, column))
            sites.live().set_only_sites()
            self.show()
        else:
            html.write(
                _("Command %s/%d not found") %
                (html.attrencode(column), state))
Пример #21
0
def page_view():
    view_name = html.request.var("view_name")
    if not view_name:
        return page_index()

    view_spec = views.get_permitted_views().get(view_name)
    if not view_spec:
        raise MKUserError("view_name", "No view defined with the name '%s'." % view_name)

    datasource = data_source_registry[view_spec["datasource"]]()
    context = visuals.get_merged_context(
        visuals.get_context_from_uri_vars(datasource.infos),
        view_spec["context"],
    )

    view = views.View(view_name, view_spec, context)
    view.row_limit = views.get_limit()
    view.only_sites = views.get_only_sites()
    view.user_sorters = views.get_user_sorters()

    title = views.view_title(view_spec)
    mobile_html_head(title)

    painter_options = PainterOptions.get_instance()
    painter_options.load(view_name)

    try:
        view_renderer = MobileViewRenderer(view)
        views.show_view(view, view_renderer)
    except Exception as e:
        logger.exception("error showing mobile view")
        if config.debug:
            raise
        html.write("ERROR showing view: %s" % html.attrencode(e))

    mobile_html_foot()
Пример #22
0
    def _show_user_list(self):
        visible_custom_attrs = [
            (name, attr) for name, attr in userdb.get_user_attributes() if attr.show_in_table()
        ]

        users = userdb.load_users()

        entries = users.items()

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

        roles = userdb.load_roles()
        timeperiods = watolib.timeperiods.load_timeperiods()
        contact_groups = load_contact_group_information()

        with table_element("users", None, empty_text=_("No users are defined yet.")) as table:
            online_threshold = time.time() - config.user_online_maxage
            for uid, user in sorted(entries, key=lambda x: x[1].get("alias", x[0]).lower()):
                table.row()

                # Checkboxes
                table.cell(html.render_input("_toggle_group",
                                             type_="button",
                                             class_="checkgroup",
                                             onclick="cmk.selection.toggle_all_rows();",
                                             value='X'),
                           sortable=False,
                           css="checkbox")

                if uid != config.user.id:
                    html.checkbox("_c_user_%s" % base64.b64encode(uid.encode("utf-8")))

                user_connection_id = userdb.cleanup_connection_id(user.get('connector'))
                connection = userdb.get_connection(user_connection_id)

                # Buttons
                table.cell(_("Actions"), css="buttons")
                if connection:  # only show edit buttons when the connector is available and enabled
                    edit_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                               ("edit", uid)])
                    html.icon_button(edit_url, _("Properties"), "edit")

                    clone_url = watolib.folder_preserving_link([("mode", "edit_user"),
                                                                ("clone", uid)])
                    html.icon_button(clone_url, _("Create a copy of this user"), "clone")

                delete_url = make_action_link([("mode", "users"), ("_delete", uid)])
                html.icon_button(delete_url, _("Delete"), "delete")

                notifications_url = watolib.folder_preserving_link([("mode", "user_notifications"),
                                                                    ("user", uid)])
                if watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    html.icon_button(notifications_url, _("Custom notification table of this user"),
                                     "notifications")

                # ID
                table.cell(_("ID"), uid)

                # Online/Offline
                if config.save_user_access_times:
                    last_seen = user.get('last_seen', 0)
                    if last_seen >= online_threshold:
                        title = _('Online')
                        img_txt = 'online'
                    elif last_seen != 0:
                        title = _('Offline')
                        img_txt = 'offline'
                    elif last_seen == 0:
                        title = _('Never logged in')
                        img_txt = 'inactive'

                    title += ' (%s %s)' % (render.date(last_seen), render.time_of_day(last_seen))
                    table.cell(_("Act."))
                    html.icon(title, img_txt)

                    table.cell(_("Last seen"))
                    if last_seen != 0:
                        html.write_text("%s %s" %
                                        (render.date(last_seen), render.time_of_day(last_seen)))
                    else:
                        html.write_text(_("Never logged in"))

                if cmk.is_managed_edition():
                    table.cell(_("Customer"), managed.get_customer_name(user))

                # Connection
                if connection:
                    table.cell(_("Connection"),
                               '%s (%s)' % (connection.short_title(), user_connection_id))
                    locked_attributes = userdb.locked_attributes(user_connection_id)
                else:
                    table.cell(_("Connection"),
                               "%s (%s) (%s)" % (_("UNKNOWN"), user_connection_id, _("disabled")),
                               css="error")
                    locked_attributes = []

                # Authentication
                if "automation_secret" in user:
                    auth_method = _("Automation")
                elif user.get("password") or 'password' in locked_attributes:
                    auth_method = _("Password")
                else:
                    auth_method = "<i>%s</i>" % _("none")
                table.cell(_("Authentication"), auth_method)

                table.cell(_("State"))
                if user.get("locked", False):
                    html.icon(_('The login is currently locked'), 'user_locked')

                if "disable_notifications" in user and isinstance(user["disable_notifications"],
                                                                  bool):
                    disable_notifications_opts = {"disable": user["disable_notifications"]}
                else:
                    disable_notifications_opts = user.get("disable_notifications", {})

                if disable_notifications_opts.get("disable", False):
                    html.icon(_('Notifications are disabled'), 'notif_disabled')

                # Full name / Alias
                table.text_cell(_("Alias"), user.get("alias", ""))

                # Email
                table.text_cell(_("Email"), user.get("email", ""))

                # Roles
                table.cell(_("Roles"))
                if user.get("roles", []):
                    role_links = [(watolib.folder_preserving_link([("mode", "edit_role"),
                                                                   ("edit", role)]),
                                   roles[role].get("alias")) for role in user["roles"]]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(alias, href=link) for (link, alias) in role_links))

                # contact groups
                table.cell(_("Contact groups"))
                cgs = user.get("contactgroups", [])
                if cgs:
                    cg_aliases = [
                        contact_groups[c]['alias'] if c in contact_groups else c for c in cgs
                    ]
                    cg_urls = [
                        watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                        ("edit", c)]) for c in cgs
                    ]
                    html.write_html(
                        HTML(", ").join(
                            html.render_a(content, href=url)
                            for (content, url) in zip(cg_aliases, cg_urls)))
                else:
                    html.i(_("none"))

                #table.cell(_("Sites"))
                #html.write(vs_authorized_sites().value_to_text(user.get("authorized_sites",
                #                                                vs_authorized_sites().default_value())))

                # notifications
                if not watolib.load_configuration_settings().get("enable_rulebased_notifications"):
                    table.cell(_("Notifications"))
                    if not cgs:
                        html.i(_("not a contact"))
                    elif not user.get("notifications_enabled", True):
                        html.write_text(_("disabled"))
                    elif user.get("host_notification_options", "") == "" and \
                         user.get("service_notification_options", "") == "":
                        html.write_text(_("all events disabled"))
                    else:
                        tp = user.get("notification_period", "24X7")
                        if tp not in timeperiods:
                            tp = tp + _(" (invalid)")
                        elif tp not in watolib.timeperiods.builtin_timeperiods():
                            url = watolib.folder_preserving_link([("mode", "edit_timeperiod"),
                                                                  ("edit", tp)])
                            tp = html.render_a(timeperiods[tp].get("alias", tp), href=url)
                        else:
                            tp = timeperiods[tp].get("alias", tp)
                        html.write(tp)

                # the visible custom attributes
                for name, attr in visible_custom_attrs:
                    vs = attr.valuespec()
                    table.cell(html.attrencode(_u(vs.title())))
                    html.write(vs.value_to_text(user.get(name, vs.default_value())))

        html.button("_bulk_delete_users", _("Bulk Delete"), "submit", style="margin-top:10px")
        html.hidden_fields()
        html.end_form()

        if not load_contact_group_information():
            url = "wato.py?mode=contact_groups"
            html.open_div(class_="info")
            html.write(
                _("Note: you haven't defined any contact groups yet. If you <a href='%s'>"
                  "create some contact groups</a> you can assign users to them und thus "
                  "make them monitoring contacts. Only monitoring contacts can receive "
                  "notifications.") % url)
            html.write(" you can assign users to them und thus "
                       "make them monitoring contacts. Only monitoring contacts can receive "
                       "notifications.")
            html.close_div()
Пример #23
0
def test_htmllib_integration(register_builtin_html):
    assert type(html.escaper) == htmllib.Escaper

    assert html.attrencode("") == ""
    assert html.permissive_attrencode("") == ""
Пример #24
0
def heading(text):
    html.write("<h3>%s</h3>\n" % html.attrencode(text))
Пример #25
0
 def render(self, row, cell):
     return ("", html.attrencode(row["aggr_name"]))
Пример #26
0
    def _render_headers(self, actions_enabled, actions_visible, empty_columns):
        if self.options["omit_headers"]:
            return

        table_id = self.id

        html.open_tr()
        first_col = True
        for nr, (header, css, help_txt, sortable) in enumerate(self.headers):
            if self.options["omit_empty_columns"] and empty_columns[nr]:
                continue

            text = header

            if help_txt:
                header = '<span title="%s">%s</span>' % (
                    html.attrencode(help_txt), header)

            css_class = "header_%s" % css if css else None

            if not self.options["sortable"] or not sortable:
                html.open_th(class_=css_class)
            else:
                reverse = 0
                sort = html.request.var('_%s_sort' % table_id)
                if sort:
                    sort_col, sort_reverse = map(int, sort.split(',', 1))
                    if sort_col == nr:
                        reverse = 1 if sort_reverse == 0 else 0

                action_uri = html.makeactionuri([('_%s_sort' % table_id,
                                                  '%d,%d' % (nr, reverse))])
                html.open_th(class_=["sort", css_class],
                             title=_("Sort by %s") % text,
                             onclick="location.href='%s'" % action_uri)

            # Add the table action link
            if first_col:
                first_col = False
                if actions_enabled:
                    if not header:
                        header = "&nbsp;"  # Fixes layout problem with white triangle
                    if actions_visible:
                        state = '0'
                        help_txt = _('Hide table actions')
                        img = 'table_actions_on'
                    else:
                        state = '1'
                        help_txt = _('Display table actions')
                        img = 'table_actions_off'
                    html.open_div(class_=["toggle_actions"])
                    html.icon_button(html.makeuri([('_%s_actions' % table_id,
                                                    state)]),
                                     help_txt,
                                     img,
                                     cssclass='toggle_actions')
                    html.open_span()
                    html.write(header)
                    html.close_span()
                    html.close_div()
                else:
                    html.write(header)
            else:
                html.write(header)

            html.close_th()
        html.close_tr()
Пример #27
0
def _transform_builtin_dashboards():
    # type: () -> None
    if 'builtin_dashboards_transformed' in g:
        return  # Only do this once
    for name, dashboard in builtin_dashboards.items():
        # Do not transform dashboards which are already in the new format
        if 'context' in dashboard:
            continue

        # Transform the dashlets
        for nr, dashlet in enumerate(dashboard['dashlets']):
            dashlet.setdefault('show_title', True)

            if dashlet.get('url', '').startswith('dashlet_hoststats') or \
                dashlet.get('url', '').startswith('dashlet_servicestats'):

                # hoststats and servicestats
                dashlet['type'] = dashlet['url'][8:].split('.', 1)[0]

                if '?' in dashlet['url']:
                    # Transform old parameters:
                    # wato_folder
                    # host_contact_group
                    # service_contact_group
                    paramstr = dashlet['url'].split('?', 1)[1]
                    dashlet['context'] = {}
                    for key, val in [
                            p.split('=', 1) for p in paramstr.split('&')
                    ]:
                        if key == 'host_contact_group':
                            dashlet['context']['opthost_contactgroup'] = {
                                'neg_opthost_contact_group': '',
                                'opthost_contact_group': val,
                            }
                        elif key == 'service_contact_group':
                            dashlet['context']['optservice_contactgroup'] = {
                                'neg_optservice_contact_group': '',
                                'optservice_contact_group': val,
                            }
                        elif key == 'wato_folder':
                            dashlet['context']['wato_folder'] = {
                                'wato_folder': val,
                            }

                del dashlet['url']

            elif dashlet.get('urlfunc') and not isinstance(
                    dashlet['urlfunc'], str):
                raise MKGeneralException(
                    _('Unable to transform dashlet %d of dashboard %s: '
                      'the dashlet is using "urlfunc" which can not be '
                      'converted automatically.') % (nr, name))

            elif dashlet.get('url', '') != '' or dashlet.get(
                    'urlfunc') or dashlet.get('iframe'):
                # Normal URL based dashlet
                dashlet['type'] = 'url'

                if dashlet.get('iframe'):
                    dashlet['url'] = dashlet['iframe']
                    del dashlet['iframe']

            elif dashlet.get('view', '') != '':
                # Transform views
                # There might be more than the name in the view definition
                view_name = dashlet['view'].split('&')[0]

                # Copy the view definition into the dashlet
                copy_view_into_dashlet(dashlet,
                                       nr,
                                       view_name,
                                       load_from_all_views=True)
                del dashlet['view']

            else:
                raise MKGeneralException(
                    _('Unable to transform dashlet %d of dashboard %s. '
                      'You will need to migrate it on your own. Definition: %r'
                      ) % (nr, name, html.attrencode(dashlet)))

            dashlet.setdefault('context', {})
            dashlet.setdefault('single_infos', [])

        # the modification time of builtin dashboards can not be checked as on user specific
        # dashboards. Set it to 0 to disable the modification chech.
        dashboard.setdefault('mtime', 0)

        dashboard.setdefault('show_title', True)
        if dashboard['title'] is None:
            dashboard['title'] = _('No title')
            dashboard['show_title'] = False

        dashboard.setdefault('single_infos', [])
        dashboard.setdefault('context', {})
        dashboard.setdefault('topic', _('Overview'))
        dashboard.setdefault('description', dashboard.get('title', ''))
    g.builtin_dashboards_transformed = True
Пример #28
0
def _show_output_box(title, content):
    html.h3(title)
    html.open_div(class_="log_output")
    html.write(
        html.attrencode(content).replace("\n", "<br>").replace(' ', '&nbsp;'))
    html.close_div()
Пример #29
0
    def _show_host_row(self, rendered_hosts, table, hostname, search_text,
                       show_checkboxes, colspan, host_errors,
                       contact_group_names):
        if search_text and (search_text.lower() not in hostname.lower()):
            return

        host = self._folder.host(hostname)
        rendered_hosts.append(hostname)
        effective = host.effective_attributes()

        table.row()

        # Column with actions (buttons)

        if show_checkboxes:
            table.cell(html.render_input(
                "_toggle_group",
                type_="button",
                class_="checkgroup",
                onclick="cmk.selection.toggle_all_rows();",
                value='X'),
                       sortable=False,
                       css="checkbox")
            # Use CSS class "failed" in order to provide information about
            # selective toggling inventory-failed hosts for Javascript
            html.input(name="_c_%s" % hostname,
                       type_="checkbox",
                       value=colspan,
                       class_="failed" if host.discovery_failed() else None)
            html.label("", "_c_%s" % hostname)

        table.cell(_("Actions"), css="buttons", sortable=False)
        self._show_host_actions(host)

        # Hostname with link to details page (edit host)
        table.cell(_("Hostname"))
        errors = host_errors.get(hostname, []) + host.validation_errors()
        if errors:
            msg = _("Warning: This host has an invalid configuration: ")
            msg += ", ".join(errors)
            html.icon(msg, "validation_error")
            html.nbsp()

        if host.is_offline():
            html.icon(_("This host is disabled"), "disabled")
            html.nbsp()

        if host.is_cluster():
            html.icon(
                _("This host is a cluster of %s") %
                ", ".join(host.cluster_nodes()), "cluster")
            html.nbsp()

        html.a(hostname, href=host.edit_url())

        # Show attributes
        for attr in host_attribute_registry.attributes():
            if attr.show_in_table():
                attrname = attr.name()
                if attrname in host.attributes():
                    tdclass, tdcontent = attr.paint(
                        host.attributes()[attrname], hostname)
                else:
                    tdclass, tdcontent = attr.paint(effective.get(attrname),
                                                    hostname)
                    tdclass += " inherited"
                table.cell(attr.title(),
                           html.attrencode(tdcontent),
                           css=tdclass)

        # Am I authorized?
        reason = host.reason_why_may_not("read")
        if not reason:
            icon = "authok"
            title = _("You have permission to this host.")
        else:
            icon = "autherr"
            title = html.strip_tags(reason)

        table.cell(_('Auth'),
                   html.render_icon(icon, title),
                   css="buttons",
                   sortable=False)

        # Permissions and Contact groups - through complete recursion and inhertance
        permitted_groups, host_contact_groups, _use_for_services = host.groups(
        )
        table.cell(
            _("Permissions"),
            HTML(", ").join([
                self._render_contact_group(contact_group_names, g)
                for g in permitted_groups
            ]))
        table.cell(
            _("Contact Groups"),
            HTML(", ").join([
                self._render_contact_group(contact_group_names, g)
                for g in host_contact_groups
            ]))

        if not config.wato_hide_hosttags:
            table.cell(_("Tags"), css="tag-ellipsis")
            tag_groups, show_all_code = self._limit_labels(host.tag_groups())
            html.write(
                cmk.gui.view_utils.render_tag_groups(tag_groups,
                                                     "host",
                                                     with_links=False))
            html.write(show_all_code)

        table.cell(_("Explicit labels"), css="tag-ellipsis")
        labels, show_all_code = self._limit_labels(host.labels())
        html.write(
            cmk.gui.view_utils.render_labels(
                labels,
                "host",
                with_links=False,
                label_sources={k: "explicit"
                               for k in labels.keys()}))
        html.write(show_all_code)

        # Located in folder
        if self._folder.is_search_folder():
            table.cell(_("Folder"))
            html.a(host.folder().alias_path(), href=host.folder().url())
Пример #30
0
    def _show_test_row(self, table, test_id, test_results_by_site, site_ids):
        table.row()

        table.cell(_("Actions"), css="buttons", sortable=False)
        html.icon_button(
            None,
            _("Toggle result details"),
            "toggle_details",
            onclick="cmk.wato.toggle_container('test_result_details_%s')" %
            test_id)

        worst_result = sorted(test_results_by_site["site_results"].values(),
                              key=lambda result: result.status)[0]

        # Disabling of test in total
        is_test_disabled = self._is_test_disabled(test_id)
        if is_test_disabled:
            html.icon_button(
                html.makeactionuri([
                    ("_do", "enable"),
                    ("_test_id", worst_result.test_id),
                ]),
                _("Reenable this test"),
                "enable_test",
            )
        else:
            html.icon_button(
                html.makeactionuri([
                    ("_do", "disable"),
                    ("_test_id", worst_result.test_id),
                ]),
                _("Disable this test"),
                "disable_test",
            )

        # assume all have the same test meta information (title, help, ...)
        table.cell(_("Title"),
                   css="title " + "stale" if is_test_disabled else "")
        html.write_text(test_results_by_site["test"]["title"])

        # Now loop all sites to display their results
        for site_id in site_ids:
            if is_test_disabled:
                table.cell(site_id, "")
                table.cell("", "")
                continue

            result = test_results_by_site["site_results"].get(site_id)
            if result is None:
                table.cell(site_id, css="state state-1")
                table.cell("", css="buttons")
                continue

            is_acknowledged = self._is_acknowledged(result)

            if is_acknowledged or result.status == -1:
                css = "state stale"
            else:
                css = "state state%d" % result.status

            table.cell(site_id, css=css)
            html.open_div(title=result.text)
            html.write_text(result.status_name())
            html.close_div()

            table.cell("", css="buttons")

            if result.status != 0:
                if is_acknowledged:
                    html.icon_button(
                        html.makeactionuri([
                            ("_do", "unack"),
                            ("_site_id", result.site_id),
                            ("_status_id", result.status),
                            ("_test_id", result.test_id),
                        ]),
                        _("Unacknowledge this test result for site %s") %
                        site_id,
                        "unacknowledge_test",
                    )
                else:
                    html.icon_button(
                        html.makeactionuri([
                            ("_do", "ack"),
                            ("_site_id", result.site_id),
                            ("_status_id", result.status),
                            ("_test_id", result.test_id),
                        ]),
                        _("Acknowledge this test result for site %s") %
                        site_id,
                        "acknowledge_test",
                    )
            else:
                html.write("")

        # Add toggleable notitication context
        table.row(class_="ac_test_details hidden",
                  id_="test_result_details_%s" % test_id)
        table.cell(colspan=2 + 2 * len(site_ids))

        html.write_text(test_results_by_site["test"]["help"])

        if not is_test_disabled:
            html.open_table()
            for site_id in site_ids:
                result = test_results_by_site["site_results"].get(site_id)
                if result is None:
                    continue

                html.open_tr()
                html.td(html.attrencode(site_id))
                html.td("%s: %s" % (result.status_name(), result.text))
                html.close_tr()
            html.close_table()

        # This dummy row is needed for not destroying the odd/even row highlighting
        table.row(class_="hidden")