Beispiel #1
0
    def render_snapin(self, snapin: UserSidebarSnapin) -> str:
        snapin_class = snapin.snapin_type
        name = snapin_class.type_name()
        snapin_instance = snapin_class()

        more_id = "sidebar_snapin_%s" % name

        show_more = user.get_show_more_setting(more_id)
        html.open_div(id_="snapin_container_%s" % name,
                      class_=["snapin", ("more" if show_more else "less")])

        self._render_snapin_styles(snapin_instance)
        # When not permitted to open/close snapins, the snapins are always opened
        if snapin.visible == SnapinVisibility.OPEN or not user.may(
                "general.configure_sidebar"):
            style = None
        else:
            style = "display:none"

        toggle_url = "sidebar_openclose.py?name=%s&state=" % name

        # If the user may modify the sidebar then add code for dragging the snapin
        head_actions: Dict[str, str] = {}
        if user.may("general.configure_sidebar"):
            head_actions = {
                "onmouseover": "document.body.style.cursor='move';",
                "onmouseout ": "document.body.style.cursor='';",
                "onmousedown": "cmk.sidebar.snapin_start_drag(event)",
                "onmouseup": "cmk.sidebar.snapin_stop_drag(event)",
            }

        html.open_div(class_=["head", snapin.visible.value], **head_actions)

        show_more = snapin_instance.has_show_more_items()
        may_configure = user.may("general.configure_sidebar")

        if show_more or may_configure:

            html.open_div(class_="snapin_buttons")

            if show_more:
                html.open_span(class_="moresnapin")
                html.more_button(more_id, dom_levels_up=4)
                html.close_span()

            if may_configure:
                # Button for closing (removing) a snapin
                html.open_span(class_="closesnapin")
                close_url = "sidebar_openclose.py?name=%s&state=off" % name
                html.icon_button(
                    url=None,
                    title=_("Remove this element"),
                    icon="close",
                    onclick="cmk.sidebar.remove_sidebar_snapin(this, '%s')" %
                    close_url,
                )
                html.close_span()

            html.close_div()

        # The heading. A click on the heading mini/maximizes the snapin
        toggle_actions: Dict[str, str] = {}
        if user.may("general.configure_sidebar"):
            toggle_actions = {
                "onclick":
                "cmk.sidebar.toggle_sidebar_snapin(this,'%s')" % toggle_url,
                "onmouseover": "this.style.cursor='pointer'",
                "onmouseout": "this.style.cursor='auto'",
            }
        html.b(
            textwrap.shorten(snapin_class.title(), width=27,
                             placeholder="..."),
            class_=["heading"],
            **toggle_actions,
        )

        if may_configure:
            # Icon for mini/maximizing
            html.span(
                "",
                class_="minisnapin",
                title=_("Open/close this element"),
                onclick="cmk.sidebar.toggle_sidebar_snapin(this, '%s')" %
                toggle_url,
            )

        # End of header
        html.close_div()

        # Now comes the content
        html.open_div(class_="content", id_="snapin_%s" % name, style=style)
        refresh_url = ""
        try:
            # TODO: Refactor this confusing special case. Add deddicated method or something
            # to let the snapins make the sidebar know that there is a URL to fetch.
            url = snapin_instance.show()
            if url is not None:
                # Fetch the contents from an external URL. Don't render it on our own.
                refresh_url = url
                html.javascript(
                    'cmk.ajax.get_url("%s", cmk.utils.update_contents, "snapin_%s")'
                    % (refresh_url, name))
        except Exception as e:
            logger.exception("error rendering snapin %s", name)
            write_snapin_exception(e)
        html.close_div()
        html.close_div()
        return refresh_url
Beispiel #2
0
    def page(self):
        watolib.init_wato_datastructures(with_wato_lock=True)

        if not user.may('wato.diag_host'):
            raise MKAuthException(_('You are not permitted to perform this action.'))

        if not transactions.check_transaction():
            raise MKAuthException(_("Invalid transaction"))

        api_request = self.webapi_request()

        hostname = api_request.get("host")
        if not hostname:
            raise MKGeneralException(_('The hostname is missing.'))

        host = watolib.Host.host(hostname)

        if not host:
            raise MKGeneralException(_('The given host does not exist.'))
        if host.is_cluster():
            raise MKGeneralException(_('This view does not support cluster hosts.'))

        host.need_permission("read")

        _test = api_request.get('_test')
        if not _test:
            raise MKGeneralException(_('The test is missing.'))

        # Execute a specific test
        if _test not in dict(ModeDiagHost.diag_host_tests()).keys():
            raise MKGeneralException(_('Invalid test.'))

        # TODO: Use ModeDiagHost._vs_rules() for processing/validation?
        args: List[str] = [u""] * 13
        for idx, what in enumerate([
                'ipaddress',
                'snmp_community',
                'agent_port',
                'snmp_timeout',
                'snmp_retries',
                'tcp_connect_timeout',
        ]):
            args[idx] = api_request.get(what, u"")

        if api_request.get("snmpv3_use"):
            snmpv3_use = {
                u"0": u"noAuthNoPriv",
                u"1": u"authNoPriv",
                u"2": u"authPriv",
            }.get(api_request.get("snmpv3_use", u""), u"")

            args[7] = snmpv3_use
            if snmpv3_use != u"noAuthNoPriv":
                snmpv3_auth_proto = {
                    str(DropdownChoice.option_id("md5")): u"md5",
                    str(DropdownChoice.option_id("sha")): u"sha"
                }.get(api_request.get("snmpv3_auth_proto", u""), u"")

                args[8] = snmpv3_auth_proto
                args[9] = api_request.get("snmpv3_security_name", u"")
                args[10] = api_request.get("snmpv3_security_password", u"")

                if snmpv3_use == "authPriv":
                    snmpv3_privacy_proto = {
                        str(DropdownChoice.option_id("DES")): u"DES",
                        str(DropdownChoice.option_id("AES")): u"AES"
                    }.get(api_request.get("snmpv3_privacy_proto", u""), u"")

                    args[11] = snmpv3_privacy_proto

                    args[12] = api_request.get("snmpv3_privacy_password", u"")
            else:
                args[9] = api_request.get("snmpv3_security_name", u"")

        result = watolib.check_mk_automation(host.site_id(), "diag-host", [hostname, _test] + args)
        return {
            "next_transid": transactions.fresh_transid(),
            "status_code": result[0],
            "output": ensure_str(result[1], errors="replace"),
        }
Beispiel #3
0
    def _vs_individual_elements(self) -> List[DictionaryEntry]:
        if user.may("wato.edit_all_passwords"):
            admin_element: List[ValueSpec] = [
                FixedValue(
                    value=None,
                    title=_("Administrators"),
                    totext=_("Administrators (having the permission "
                             '"Write access to all passwords")'),
                )
            ]
        else:
            admin_element = []

        elements: List[DictionaryEntry] = [
            (
                "password",
                PasswordValuespec(
                    title=_("Password"),
                    allow_empty=False,
                ),
            ),
            (
                "owned_by",
                Alternative(
                    title=_("Editable by"),
                    help=_(
                        "Each password is owned by a group of users which are able to edit, "
                        "delete and use existing passwords."),
                    elements=admin_element + [
                        DropdownChoice(
                            title=_("Members of the contact group:"),
                            choices=lambda: sorted_contact_group_choices(
                                only_own=True),
                            invalid_choice="complain",
                            empty_text=_(
                                "You need to be member of at least one contact group to be able to "
                                "create a password."),
                            invalid_choice_title=_(
                                "Group not existant or not member"),
                            invalid_choice_error=_(
                                "The choosen group is either not existant "
                                "anymore or you are not a member of this "
                                "group. Please choose another one."),
                        ),
                    ],
                ),
            ),
            (
                "shared_with",
                DualListChoice(
                    title=_("Share with"),
                    help=
                    _("By default only the members of the owner contact group are permitted "
                      "to use a a configured password. It is possible to share a password with "
                      "other groups of users to make them able to use a password in checks."
                      ),
                    choices=sorted_contact_group_choices,
                    autoheight=False,
                ),
            ),
        ]

        return elements
Beispiel #4
0
 def may_see(cls) -> bool:
     return user.may(cls.permission_name())
Beispiel #5
0
    def __init__(self):
        super().__init__()

        if not user.may("wato.rename_hosts"):
            raise MKGeneralException(_("You don't have the right to rename hosts"))
Beispiel #6
0
    def render(self, rows, view, group_cells, cells, num_columns,
               show_checkboxes):
        repeat_heading_every = 20  # in case column_headers is "repeat"

        html.open_table(class_='data table')
        last_group = None
        odd = "odd"
        column = 1
        group_open = False
        num_cells = len(cells)
        if show_checkboxes:
            num_cells += 1

        if not group_cells and view.get("column_headers") != "off":
            self._show_header_line(cells, num_columns, show_checkboxes)

        rows_with_ids = [(row_id(view, row), row) for row in rows]
        groups, rows_with_ids = calculate_view_grouping_of_services(
            rows_with_ids, row_group_cells=group_cells)

        visible_row_number = 0
        group_hidden, num_grouped_rows = None, 0
        for index, row in rows_with_ids:
            # Show group header, if a new group begins. But only if grouping
            # is activated
            if group_cells:
                this_group = group_value(row, group_cells)
                if this_group != last_group:
                    if column != 1:  # not a the beginning of a new line
                        for _i in range(column - 1, num_columns):
                            html.td('', class_="gap")
                            html.td('', class_="fillup", colspan=num_cells)
                        html.close_tr()
                        column = 1

                    group_open = True
                    visible_row_number = 0

                    # paint group header, but only if it is non-empty
                    header_is_empty = True
                    for cell in group_cells:
                        _tdclass, content = cell.render(row)
                        if content:
                            header_is_empty = False
                            break

                    if not header_is_empty:
                        html.open_tr(class_="groupheader")
                        html.open_td(class_="groupheader",
                                     colspan=(num_cells * (num_columns + 2) +
                                              (num_columns - 1)))
                        html.open_table(class_="groupheader",
                                        cellspacing="0",
                                        cellpadding="0",
                                        border="0")
                        html.open_tr()
                        painted = False
                        for cell in group_cells:
                            if painted:
                                html.td(', ')
                            painted = cell.paint(row)

                        html.close_tr()
                        html.close_table()
                        html.close_td()
                        html.close_tr()
                        odd = "odd"

                    # Table headers
                    if view.get("column_headers") != "off":
                        self._show_header_line(cells, num_columns,
                                               show_checkboxes)
                    last_group = this_group

            # Should we wrap over to a new line?
            if column >= num_columns + 1:
                html.close_tr()
                column = 1

            # At the beginning of the line? Beginn new line
            if column == 1:
                if view.get("column_headers") == "repeat":
                    if visible_row_number > 0 and visible_row_number % repeat_heading_every == 0:
                        self._show_header_line(cells, num_columns,
                                               show_checkboxes)
                visible_row_number += 1

                # In one-column layout we use the state of the service
                # or host - if available - to color the complete line
                if num_columns == 1:
                    # render state, if available through whole tr
                    if not row.get('service_description'):
                        state = row.get("host_state", 0)
                        if state > 0:
                            state += 1  # 1 is critical for hosts
                    else:
                        state = row.get("service_state", 0)
                else:
                    state = 0

                if index in groups:
                    group_spec, num_grouped_rows = groups[index]
                    group_hidden = grouped_row_title(index, group_spec,
                                                     num_grouped_rows, odd,
                                                     num_cells)
                    odd = "even" if odd == "odd" else "odd"

                css_classes = []

                hide = ""
                if num_grouped_rows > 0:
                    num_grouped_rows -= 1
                    if group_hidden:
                        hide = "display:none"

                if group_hidden is not None and num_grouped_rows == 0:
                    # last row in group
                    css_classes.append("group_end")
                    group_hidden = None

                odd = "even" if odd == "odd" else "odd"

                if num_columns > 1:
                    css_classes.append("multicolumn")
                css_classes += ["%s%d" % (odd, state)]

                html.open_tr(class_=["data"] + css_classes, style=hide)

            # Not first columns: Create one empty column as separator
            else:
                html.open_td(class_="gap")
                html.close_td()

            if show_checkboxes:
                render_checkbox_td(view, row, num_cells)

            for cell in cells:
                cell.paint(row)

            column += 1

        if group_open:
            for _i in range(column - 1, num_columns):
                html.td('', class_="gap")
                html.td('', class_="fillup", colspan=num_cells)
            html.close_tr()
        html.close_table()
        if not user.may("general.act"):
            return

        init_rowselect(_get_view_name(view))
Beispiel #7
0
    def _show_rows(self):
        rows = self._get_rows()

        if bool([r for r in rows if r.stats is None]):
            html.center(_("No data from any site"))
            return

        html.open_table(class_=["tacticaloverview"], cellspacing="2", cellpadding="0", border="0")

        show_stales = self.parameters()["show_stale"] and user.may(
            "general.see_stales_in_tactical_overview"
        )
        has_stale_objects = bool([r for r in rows if r.what != "events" and r.stats[-1]])

        for row in rows:
            if row.what == "events":
                amount, problems, unhandled_problems = row.stats
                stales = 0

                # no events open and disabled in local site: don't show events
                if amount == 0 and not config.mkeventd_enabled:
                    continue
            else:
                amount, problems, unhandled_problems, stales = row.stats

            context_vars = get_context_url_variables(row.context)

            html.open_tr()
            html.th(row.title)
            html.th(_("Problems"), class_="show_more_mode")
            html.th(
                html.render_span(_("Unhandled"), class_="more")
                + html.render_span(_("Unhandled p."), class_="less")
            )
            if show_stales and has_stale_objects:
                html.th(_("Stale"))
            html.close_tr()

            td_class = "col4" if has_stale_objects else "col3"

            html.open_tr()
            url = makeuri_contextless(request, row.views.total + context_vars, filename="view.py")
            html.open_td(class_=["total", td_class])
            html.a("%s" % amount, href=url, target="main")
            html.close_td()

            for value, ty in [(problems, "handled"), (unhandled_problems, "unhandled")]:
                url = makeuri_contextless(
                    request,
                    getattr(row.views, ty) + context_vars,
                    filename="view.py",
                )
                html.open_td(
                    class_=[
                        td_class,
                        "states prob" if value != 0 else None,
                        "show_more_mode" if ty == "handled" else "basic",
                    ]
                )
                link(str(value), url)
                html.close_td()

            if show_stales and has_stale_objects:
                if row.views.stale:
                    url = makeuri_contextless(
                        request,
                        row.views.stale + context_vars,
                        filename="view.py",
                    )
                    html.open_td(class_=[td_class, "states prob" if stales != 0 else None])
                    link(str(stales), url)
                    html.close_td()
                else:
                    html.td(html.render_span("0"))

            html.close_tr()
        html.close_table()
Beispiel #8
0
    def render(
        self,
        rows: Rows,
        show_checkboxes: bool,
        num_columns: int,
        show_filters: List[Filter],
        unfiltered_amount_of_rows: int,
    ) -> None:
        view_spec = self.view.spec
        home = ("mobile.py", "Home", "home")

        page = request.var("page")
        if not page:
            if view_spec.get("mustsearch"):
                page = "filter"
            else:
                page = "data"

        title = views.view_title(self.view.spec, self.view.context)
        navbar = [
            ("data", _("Results"), "grid", "results_button"),
            ("filter", _("Filter"), "search", ""),
        ]
        if user.may("general.act"):
            navbar.append(("commands", _("Commands"), "gear", ""))

        # Should we show a page with context links?
        context_links = list(
            views.collect_context_links(self.view,
                                        rows,
                                        mobile=True,
                                        visual_types=["views"]))

        if context_links:
            navbar.append(("context", _("Context"), "arrow-r", ""))
        page_id = "view_" + view_spec["name"]

        if page == "filter":
            jqm_page_header(_("Filter / Search"),
                            left_button=home,
                            id_="filter")
            _show_filter_form(show_filters)
            jqm_page_navfooter(navbar, "filter", page_id)

        elif page == "commands":
            # Page: Commands
            if user.may("general.act"):
                jqm_page_header(_("Commands"),
                                left_button=home,
                                id_="commands")
                show_commands = True
                if request.has_var("_do_actions"):
                    try:
                        show_commands = do_commands(
                            self.view.datasource.infos[0], rows)
                    except MKUserError as e:
                        html.user_error(e)
                        show_commands = True
                if show_commands:
                    _show_command_form(self.view.datasource, rows)
                jqm_page_navfooter(navbar, "commands", page_id)

        elif page == "data":
            # Page: data rows of view
            jqm_page_header(
                title,
                left_button=home,
                right_button=("javascript:document.location.reload();",
                              _("Reload"), "refresh"),
                id_="data",
            )
            html.open_div(id_="view_results")
            if len(rows) == 0:
                html.write_text(_("No hosts/services found."))
            else:
                try:
                    if cmk.gui.view_utils.row_limit_exceeded(
                            unfiltered_amount_of_rows, self.view.row_limit):
                        cmk.gui.view_utils.query_limit_exceeded_warn(
                            self.view.row_limit, user)
                        del rows[self.view.row_limit:]
                    self.view.layout.render(
                        rows,
                        view_spec,
                        self.view.group_cells,
                        self.view.row_cells,
                        num_columns,
                        show_checkboxes and not html.do_actions(),
                    )
                except Exception as e:
                    logger.exception("error rendering mobile view")
                    html.write_text(_("Error showing view: %s") % e)
            html.close_div()
            jqm_page_navfooter(navbar, "data", page_id)

        # Page: Context buttons
        elif page == "context":
            jqm_page_header(_("Context"), left_button=home, id_="context")
            _show_context_links(context_links)
            jqm_page_navfooter(navbar, "context", page_id)
Beispiel #9
0
def may_override():
    return user.id in config.wato_read_only["rw_users"] or (
        request.var("mode") == "read_only" and user.may("wato.set_read_only"))
Beispiel #10
0
def _user_menu_topics() -> List[TopicMenuTopic]:
    quick_items = [
        TopicMenuItem(
            name="ui_theme",
            title=_("Interface theme"),
            url='javascript:cmk.sidebar.toggle_user_attribute("ajax_ui_theme.py")',
            target="",
            sort_index=10,
            icon="color_mode",
            button_title=_get_current_theme_titel(),
        ),
        TopicMenuItem(
            name="sidebar_position",
            title=_("Sidebar position"),
            url='javascript:cmk.sidebar.toggle_user_attribute("ajax_sidebar_position.py")',
            target="",
            sort_index=20,
            icon="sidebar_position",
            button_title=_sidebar_position_title(_get_sidebar_position()),
        ),
    ]

    items = [
        TopicMenuItem(
            name="change_password",
            title=_("Change password"),
            url="user_change_pw.py",
            sort_index=10,
            icon="topic_change_password",
        ),
        TopicMenuItem(
            name="user_profile",
            title=_("Edit profile"),
            url="user_profile.py",
            sort_index=20,
            icon="topic_profile",
        ),
        TopicMenuItem(
            name="logout",
            title=_("Logout"),
            url="logout.py",
            sort_index=30,
            icon="sidebar_logout",
        ),
    ]

    if rulebased_notifications_enabled() and user.may("general.edit_notifications"):
        items.insert(
            1,
            TopicMenuItem(
                name="notification_rules",
                title=_("Notification rules"),
                url="wato.py?mode=user_notifications_p",
                sort_index=30,
                icon="topic_events",
            ),
        )

    return [
        TopicMenuTopic(
            name="user",
            title=_("Quick toggle"),
            # TODO(rb): set correct icon
            icon="topic_profile",
            items=quick_items,
        ),
        TopicMenuTopic(
            name="user",
            title=_("Profile"),
            icon="topic_profile",
            items=items,
        ),
    ]
 def is_visible(self):
     if user.may("background_jobs.see_foreign_jobs"):
         return True
     return user.id == self.get_status().get("user")
Beispiel #12
0
    def page(self):
        if not user.may("wato.diag_host"):
            raise MKAuthException(
                _("You are not permitted to perform this action."))

        if not transactions.check_transaction():
            raise MKAuthException(_("Invalid transaction"))

        api_request = self.webapi_request()

        hostname = api_request.get("host")
        if not hostname:
            raise MKGeneralException(_("The hostname is missing."))

        host = watolib.Host.host(hostname)

        if not host:
            raise MKGeneralException(_("The given host does not exist."))
        if host.is_cluster():
            raise MKGeneralException(
                _("This view does not support cluster hosts."))

        host.need_permission("read")

        _test = api_request.get("_test")
        if not _test:
            raise MKGeneralException(_("The test is missing."))

        # Execute a specific test
        if _test not in dict(ModeDiagHost.diag_host_tests()).keys():
            raise MKGeneralException(_("Invalid test."))

        # TODO: Use ModeDiagHost._vs_rules() for processing/validation?
        args: List[str] = [""] * 13
        for idx, what in enumerate([
                "ipaddress",
                "snmp_community",
                "agent_port",
                "snmp_timeout",
                "snmp_retries",
                "tcp_connect_timeout",
        ]):
            args[idx] = api_request.get(what, "")

        if api_request.get("snmpv3_use"):
            snmpv3_use = {
                "0": "noAuthNoPriv",
                "1": "authNoPriv",
                "2": "authPriv",
            }.get(api_request.get("snmpv3_use", ""), "")

            args[7] = snmpv3_use
            if snmpv3_use != "noAuthNoPriv":
                snmpv3_auth_proto = {
                    str(DropdownChoice.option_id("md5")): "md5",
                    str(DropdownChoice.option_id("sha")): "sha",
                }.get(api_request.get("snmpv3_auth_proto", ""), "")

                args[8] = snmpv3_auth_proto
                args[9] = api_request.get("snmpv3_security_name", "")
                args[10] = api_request.get("snmpv3_security_password", "")

                if snmpv3_use == "authPriv":
                    snmpv3_privacy_proto = {
                        str(DropdownChoice.option_id("DES")): "DES",
                        str(DropdownChoice.option_id("AES")): "AES",
                    }.get(api_request.get("snmpv3_privacy_proto", ""), "")

                    args[11] = snmpv3_privacy_proto

                    args[12] = api_request.get("snmpv3_privacy_password", "")
            else:
                args[9] = api_request.get("snmpv3_security_name", "")

        result = diag_host(
            host.site_id(),
            hostname,
            _test,
            *args,
        )
        return {
            "next_transid": transactions.fresh_transid(),
            "status_code": result.return_code,
            "output": ensure_str(result.response, errors="replace"),
        }
Beispiel #13
0
def _user_is_authorized() -> bool:
    return user.may("general.agent_pairing")
Beispiel #14
0
 def may_see_hosts():
     return user.may("wato.use") and (user.may("wato.seeall") or user.may("wato.hosts"))
Beispiel #15
0
    def _render_group(self, rows_with_ids, header, view, group_cells, cells,
                      num_columns, show_checkboxes):
        repeat_heading_every = 20  # in case column_headers is "repeat"

        if group_cells:
            self._show_group_header_table(group_cells, rows_with_ids[0][1])

        html.open_table(class_="data")
        odd = "odd"

        column_headers = view.get("column_headers")
        if column_headers != "off":
            self._show_header_line(cells, show_checkboxes)

        groups, rows_with_ids = calculate_view_grouping_of_services(
            rows_with_ids, row_group_cells=None)

        visible_row_number = 0
        group_hidden, num_grouped_rows = None, 0
        for index, row in rows_with_ids:
            if view.get("column_headers") == "repeat":
                if visible_row_number > 0 and visible_row_number % repeat_heading_every == 0:
                    self._show_header_line(cells, show_checkboxes)
            visible_row_number += 1

            odd = "even" if odd == "odd" else "odd"

            # state = row.get("service_state", row.get("aggr_state"))
            state = utils.saveint(row.get("service_state"))
            if state is None:
                state = utils.saveint(row.get("host_state", 0))
                if state > 0:
                    state += 1  # 1 is critical for hosts

            num_cells = len(cells)

            if index in groups:
                group_spec, num_grouped_rows = groups[index]
                group_hidden = grouped_row_title(index, group_spec,
                                                 num_grouped_rows, odd,
                                                 num_cells)
                odd = "even" if odd == "odd" else "odd"

            css_classes = []

            if is_stale(row):
                css_classes.append("stale")

            hide = ""
            if num_grouped_rows > 0:
                num_grouped_rows -= 1
                if group_hidden:
                    hide = "display:none"

            if group_hidden is not None and num_grouped_rows == 0:
                # last row in group
                css_classes.append("group_end")
                group_hidden = None

            css_classes.append("%s%d" % (odd, state))

            html.open_tr(class_=["data"] + css_classes, style=hide)

            if show_checkboxes:
                render_checkbox_td(view, row, num_cells)

            for cell in cells:
                cell.paint(row)

            html.close_tr()

        html.close_table()
        # Don't make rows selectable when no commands can be fired
        # Ignore "C" display option here. Otherwise the rows will not be selectable
        # after view reload.
        if not user.may("general.act"):
            return

        init_rowselect(_get_view_name(view))
Beispiel #16
0
 def _may_edit_configvar(self, varname):
     if varname in ["actions"]:
         return user.may("wato.add_or_modify_executables")
     return True
Beispiel #17
0
    def render(self, rows, view, group_cells, cells, num_columns,
               show_checkboxes):
        html.open_table(class_="data tiled")

        last_group = None
        group_open = False
        for row in rows:
            # Show group header
            if group_cells:
                this_group = group_value(row, group_cells)
                if this_group != last_group:

                    # paint group header
                    if group_open:
                        html.close_td()
                        html.close_tr()
                    html.open_tr()
                    html.open_td()
                    html.open_table(class_="groupheader")
                    html.open_tr(class_="groupheader")

                    painted = False
                    for cell in group_cells:
                        if painted:
                            html.td(', ')
                        painted = cell.paint(row)

                    html.close_tr()
                    html.close_table()

                    html.close_td()
                    html.close_tr()

                    html.open_tr()
                    html.open_td(class_="tiles")

                    group_open = True
                    last_group = this_group

            # background color of tile according to item state
            state = row.get("service_state", -1)
            if state == -1:
                hbc = row.get("host_has_been_checked", 1)
                if hbc:
                    state = row.get("host_state", 0)
                    sclass = "hhstate%d" % state
                else:
                    sclass = "hhstatep"
            else:
                hbc = row.get("service_has_been_checked", 1)
                if hbc:
                    sclass = "sstate%d" % state
                else:
                    sclass = "sstatep"

            if not group_open:
                html.open_tr()
                html.open_td(class_="tiles")
                group_open = True

            html.open_div(class_=["tile", sclass])
            html.open_table()

            # We need at least five cells
            if len(cells) < 5:
                cells = cells + ([EmptyCell(view)] * (5 - len(cells)))

            rendered = [cell.render(row) for cell in cells]

            html.open_tr()
            html.open_td(class_=["tl", rendered[1][0]])
            if show_checkboxes:
                render_checkbox(view, row, len(cells) - 1)
            html.write_text(rendered[1][1])
            html.close_td()
            html.open_td(class_=["tr", rendered[2][0]])
            html.write_text(rendered[2][1])
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.open_td(colspan=2, class_=["center", rendered[0][0]])
            html.write_text(rendered[0][1])
            html.close_td()
            html.close_tr()

            for css, cont in rendered[5:]:
                html.open_tr()
                html.open_td(colspan=2, class_=["cont", css])
                html.write_text(cont)
                html.close_td()
                html.close_tr()

            html.open_tr()
            html.open_td(class_=["bl", rendered[3][0]])
            html.write_text(rendered[3][1])
            html.close_td()
            html.open_td(class_=["br", rendered[4][0]])
            html.write_text(rendered[4][1])
            html.close_td()
            html.close_tr()

            html.close_table()
            html.close_div()

        if group_open:
            html.close_td()
            html.close_tr()

        html.close_table()
        if not user.may("general.act"):
            return

        init_rowselect(_get_view_name(view))
Beispiel #18
0
def page_menu_host_entries(mode_name: str,
                           host: CREHost) -> Iterator[PageMenuEntry]:
    if mode_name != "edit_host":
        yield PageMenuEntry(
            title=_("Properties"),
            icon_name="edit",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "edit_host"),
                                                ("host", host.name())])),
        )

    if mode_name != "inventory":
        yield PageMenuEntry(
            title=_("Service configuration"),
            icon_name="services",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "inventory"),
                                                ("host", host.name())])),
        )

    if mode_name != "diag_host" and not host.is_cluster():
        yield PageMenuEntry(
            title=_("Connection tests"),
            icon_name="diagnose",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "diag_host"),
                                                ("host", host.name())])),
        )

    if mode_name != "object_parameters" and user.may("wato.rulesets"):
        yield PageMenuEntry(
            title=_("Effective parameters"),
            icon_name="rulesets",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "object_parameters"),
                                                ("host", host.name())])),
        )

    if mode_name == "object_parameters" or mode_name == "edit_host" and user.may(
            "wato.rulesets"):
        yield PageMenuEntry(
            title=_("Rules"),
            icon_name="rulesets",
            item=make_simple_link(
                makeuri_contextless(
                    request,
                    [
                        ("mode", "rule_search"),
                        ("filled_in", "search"),
                        ("search_p_ruleset_deprecated", "OFF"),
                        ("search_p_rule_host_list_USE", "ON"),
                        ("search_p_rule_host_list", host.name()),
                    ],
                    filename="wato.py",
                )),
        )

    yield make_host_status_link(host_name=host.name(), view_name="hoststatus")

    if user.may("wato.rulesets") and host.is_cluster():
        yield PageMenuEntry(
            title=_("Clustered services"),
            icon_name="rulesets",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "edit_ruleset"),
                                                ("varname",
                                                 "clustered_services")])),
        )

    if watolib.has_agent_bakery() and user.may("wato.download_agents"):
        yield PageMenuEntry(
            title=_("Monitoring agent"),
            icon_name="agents",
            item=make_simple_link(
                watolib.folder_preserving_link([("mode", "agent_of_host"),
                                                ("host", host.name())])),
        )

    if mode_name == "edit_host" and not host.locked():
        if user.may("wato.rename_hosts"):
            yield PageMenuEntry(
                title=_("Rename"),
                icon_name="rename_host",
                item=make_simple_link(
                    watolib.folder_preserving_link([("mode", "rename_host"),
                                                    ("host", host.name())])),
            )

        if user.may("wato.manage_hosts") and user.may("wato.clone_hosts"):
            yield PageMenuEntry(
                title=_("Clone"),
                icon_name="insert",
                item=make_simple_link(host.clone_url()),
            )

        yield PageMenuEntry(
            title=_("Delete"),
            icon_name="delete",
            item=make_simple_link(
                make_confirm_link(
                    url=makeactionuri(request, transactions,
                                      [("delete", "1")]),
                    message=_(
                        "Do you really want to delete the host <tt>%s</tt>?") %
                    host.name(),
                )),
        )

        if user.may("wato.auditlog"):
            yield PageMenuEntry(
                title=_("Audit log"),
                icon_name="auditlog",
                item=make_simple_link(
                    make_object_audit_log_url(host.object_ref())),
            )
Beispiel #19
0
    def _activation_status(self):
        with table_element("site-status",
                           searchable=False,
                           sortable=False,
                           css="activation") as table:

            for site_id, site in sort_sites(activation_sites()):
                table.row()

                site_status, status = self._get_site_status(site_id, site)

                is_online = self._site_is_online(status)
                is_logged_in = self._site_is_logged_in(site_id, site)
                has_foreign = self._site_has_foreign_changes(site_id)
                can_activate_all = not has_foreign or user.may(
                    "wato.activateforeign")

                # Disable actions for offline sites and not logged in sites
                if not is_online or not is_logged_in:
                    can_activate_all = False

                need_restart = self._is_activate_needed(site_id)
                need_sync = self.is_sync_needed(site_id)
                need_action = need_restart or need_sync
                nr_changes = len(self._changes_of_site(site_id))

                # Activation checkbox
                table.cell("", css="buttons")
                if can_activate_all and nr_changes:
                    html.checkbox("site_%s" % site_id,
                                  need_action,
                                  cssclass="site_checkbox")

                # Iconbuttons
                table.cell(_("Actions"), css="buttons")

                if user.may("wato.sites"):
                    edit_url = watolib.folder_preserving_link([
                        ("mode", "edit_site"), ("site", site_id)
                    ])
                    html.icon_button(edit_url,
                                     _("Edit the properties of this site"),
                                     "edit")

                # State
                if can_activate_all and need_sync:
                    html.icon_button(
                        url="javascript:void(0)",
                        id_="activate_%s" % site_id,
                        cssclass="activate_site",
                        title=
                        _("This site is not update and needs a replication. Start it now."
                          ),
                        icon="need_replicate",
                        onclick='cmk.activation.activate_changes("site", "%s")'
                        % site_id,
                    )

                if can_activate_all and need_restart:
                    html.icon_button(
                        url="javascript:void(0)",
                        id_="activate_%s" % site_id,
                        cssclass="activate_site",
                        title=
                        _("This site needs a restart for activating the changes. Start it now."
                          ),
                        icon="need_restart",
                        onclick='cmk.activation.activate_changes("site", "%s")'
                        % site_id,
                    )

                if can_activate_all and not need_action:
                    html.icon("siteuptodate", _("This site is up-to-date."))

                site_url = site.get("multisiteurl")
                if site_url:
                    html.icon_button(
                        site_url,
                        _("Open this site's local web user interface"),
                        "url",
                        target="_blank",
                    )

                table.cell(_("Site"),
                           site.get("alias", site_id),
                           css="narrow nobr")

                # Livestatus
                table.cell(_("Status"), css="narrow nobr")
                html.status_label(content=status,
                                  status=status,
                                  title=_("This site is %s") % status)

                # Livestatus-/Checkmk-Version
                table.cell(_("Version"),
                           site_status.get("livestatus_version", ""),
                           css="narrow nobr")

                table.cell(_("Changes"),
                           "%d" % nr_changes,
                           css="number narrow nobr")

                table.cell(_("Progress"), css="repprogress")
                html.open_div(id_="site_%s_status" % site_id, class_=["msg"])
                html.close_div()
                html.open_div(id_="site_%s_progress" % site_id,
                              class_=["progress"])
                html.close_div()

                table.cell(_("Details"), css="details")
                html.open_div(id_="site_%s_details" % site_id)

                last_state = self._last_activation_state(site_id)

                if not is_logged_in:
                    html.write_text(_("Is not logged in.") + " ")

                if not last_state:
                    html.write_text(_("Has never been activated"))
                elif (need_action and last_state["_state"]
                      == cmk.gui.watolib.activate_changes.STATE_SUCCESS):
                    html.write_text(_("Activation needed"))
                else:
                    html.javascript(
                        "cmk.activation.update_site_activation_state(%s);" %
                        json.dumps(last_state))

                html.close_div()
Beispiel #20
0
def _wato_page_handler(current_mode: str,
                       mode_permissions: Optional[List[PermissionName]],
                       mode_class: Type[WatoMode]) -> None:
    # Check general permission for this mode
    if mode_permissions is not None and not user.may("wato.seeall"):
        _ensure_mode_permissions(mode_permissions)

    mode = mode_class()

    # Do actions (might switch mode)
    if transactions.is_transaction():
        try:
            user.need_permission("wato.edit")

            # Even if the user has seen this mode because auf "seeall",
            # he needs an explicit access permission for doing changes:
            if user.may("wato.seeall"):
                if mode_permissions:
                    _ensure_mode_permissions(mode_permissions)

            if (cmk.gui.watolib.read_only.is_enabled()
                    and not cmk.gui.watolib.read_only.may_override()):
                raise MKUserError(None, cmk.gui.watolib.read_only.message())

            result = mode.action()
            if isinstance(result, (tuple, str, bool)):
                raise MKGeneralException(
                    f'WatoMode "{current_mode}" returns unsupported return value: {result!r}'
                )

            # We assume something has been modified and increase the config generation ID by one.
            update_config_generation()

            if config.wato_use_git:
                do_git_commit()

            # Handle two cases:
            # a) Don't render the page content after action
            #    (a confirm dialog is displayed by the action, or a non-HTML content was sent)
            # b) Redirect to another page
            if isinstance(result, FinalizeRequest):
                raise result

        except MKUserError as e:
            user_errors.add(e)

        except MKAuthException as e:
            user_errors.add(MKUserError(None, e.args[0]))

    breadcrumb = make_main_menu_breadcrumb(
        mode.main_menu()) + mode.breadcrumb()
    page_menu = mode.page_menu(breadcrumb)
    wato_html_head(
        title=mode.title(),
        breadcrumb=breadcrumb,
        page_menu=page_menu,
        show_body_start=display_options.enabled(display_options.H),
        show_top_heading=display_options.enabled(display_options.T),
    )

    if not transactions.is_transaction() or (
            cmk.gui.watolib.read_only.is_enabled()
            and cmk.gui.watolib.read_only.may_override()):
        _show_read_only_warning()

    # Show outcome of failed action on this page
    html.show_user_errors()

    # Show outcome of previous page (that redirected to this one)
    for message in get_flashed_messages():
        html.show_message(message)

    # Show content
    mode.handle_page()

    if is_sidebar_reload_needed():
        html.reload_whole_page()

    wato_html_footer(show_body_end=display_options.enabled(display_options.H))
Beispiel #21
0
def may_acknowledge():
    return user.may("general.acknowledge_werks")
Beispiel #22
0
    def _wsgi_app(self, environ: WSGIEnvironment, start_response: StartResponse) -> WSGIResponse:
        urls = self.url_map.bind_to_environ(environ)
        endpoint: Optional[Endpoint] = None
        try:
            result: Tuple[str, Mapping[str, Any]] = urls.match(return_rule=False)
            endpoint_ident, matched_path_args = result  # pylint: disable=unpacking-non-sequence
            wsgi_app = self.endpoints[endpoint_ident]
            if isinstance(wsgi_app, Authenticate):
                endpoint = wsgi_app.endpoint

            # Remove _path again (see Submount above), so the validators don't go crazy.
            path_args = {key: value for key, value in matched_path_args.items() if key != "_path"}

            # This is an implicit dependency, as we only know the args at runtime, but the
            # function at setup-time.
            environ[ARGS_KEY] = path_args

            req = Request(environ)
            resp = Response()
            with AppContext(self), RequestContext(
                req=req,
                resp=resp,
                funnel=OutputFunnel(resp),
                config_obj=config.make_config_object(config.get_default_config()),
                endpoint=endpoint,
                user=LoggedInNobody(),
                display_options=DisplayOptions(),
            ), cmk.utils.store.cleanup_locks(), sites.cleanup_connections():
                config.initialize()
                load_dynamic_permissions()
                return wsgi_app(environ, start_response)
        except ProblemException as exc:
            return exc(environ, start_response)
        except HTTPException as exc:
            # We don't want to log explicit HTTPExceptions as these are intentional.
            assert isinstance(exc.code, int)
            return problem(
                status=exc.code,
                title=http.client.responses[exc.code],
                detail=str(exc),
            )(environ, start_response)
        except MKException as exc:
            if self.debug:
                raise

            return problem(
                status=EXCEPTION_STATUS.get(type(exc), 500),
                title="An exception occurred.",
                detail=str(exc),
            )(environ, start_response)
        except Exception as exc:
            crash = APICrashReport.from_exception()
            crash_reporting.CrashReportStore().save(crash)
            logger.exception("Unhandled exception (Crash-ID: %s)", crash.ident_to_text())
            if self.debug:
                raise

            request = Request(environ)
            site = config.omd_site()
            query_string = urllib.parse.urlencode(
                [
                    ("crash_id", (crash.ident_to_text())),
                    ("site", site),
                ]
            )
            crash_url = f"{request.host_url}{site}/check_mk/crash.py?{query_string}"
            crash_details = {
                "crash_id": (crash.ident_to_text()),
                "crash_report": {
                    "href": crash_url,
                    "method": "get",
                    "rel": "cmk/crash-report",
                    "type": "text/html",
                },
            }
            if user.may("general.see_crash_reports"):
                crash_details["stack_trace"] = traceback.format_exc().split("\n")

            return problem(
                status=500,
                title=http.client.responses[500],
                detail=str(exc),
                ext=crash_details,
            )(environ, start_response)
Beispiel #23
0
def _may_see_failed_notifications() -> bool:
    return user.may("general.see_failed_notifications") or user.may(
        "general.see_failed_notifications_24h")
Beispiel #24
0
    def _wsgi_app(self, environ: WSGIEnvironment, start_response):
        urls = self.url_map.bind_to_environ(environ)
        try:
            wsgi_app, path_args = urls.match()

            # Remove this again (see Submount above), so the validators don't go crazy.
            del path_args['_path']

            # This is an implicit dependency, as we only know the args at runtime, but the
            # function at setup-time.
            environ[ARGS_KEY] = path_args
            return wsgi_app(environ, start_response)
        except HTTPException as exc:
            # We don't want to log explicit HTTPExceptions as these are intentional.
            assert isinstance(exc.code, int)
            return problem(
                status=exc.code,
                title=http.client.responses[exc.code],
                detail=str(exc),
            )(environ, start_response)
        except MKException as exc:
            if self.debug:
                raise

            return problem(
                status=EXCEPTION_STATUS.get(type(exc), 500),
                title="An exception occurred.",
                detail=str(exc),
            )(environ, start_response)
        except Exception as exc:
            crash = APICrashReport.from_exception()
            crash_reporting.CrashReportStore().save(crash)
            logger.exception("Unhandled exception (Crash-ID: %s)",
                             crash.ident_to_text())
            if self.debug:
                raise

            request = Request(environ)
            site = config.omd_site()
            query_string = urllib.parse.urlencode([
                ("crash_id", (crash.ident_to_text())),
                ("site", site),
            ])
            crash_url = f"{request.host_url}{site}/check_mk/crash.py?{query_string}"
            crash_details = {
                'crash_id': (crash.ident_to_text()),
                'crash_report': {
                    'href': crash_url,
                    'method': 'get',
                    'rel': 'cmk/crash-report',
                    'type': 'text/html',
                },
            }
            if user.may("general.see_crash_reports"):
                crash_details['stack_trace'] = traceback.format_exc().split(
                    "\n")

            return problem(
                status=500,
                title=http.client.responses[500],
                detail=str(exc),
                ext=crash_details,
            )(environ, start_response)
 def may_edit(self):
     return user.may("wato.manage_hosts")
Beispiel #26
0
 def may_see_category(self, category: str) -> bool:
     return user.may("wato.use") and self._category_permissions.get(
         category, True)