Ejemplo n.º 1
0
    def action(self) -> ActionResult:
        if not transactions.check_transaction():
            return redirect(self.mode_url())

        connections = load_connection_config(lock=True)
        if request.has_var("_delete"):
            index = request.get_integer_input_mandatory("_delete")
            connection = connections[index]
            self._add_change(
                "delete-ldap-connection",
                _("Deleted LDAP connection %s") % (connection["id"]))
            del connections[index]
            save_connection_config(connections)

        elif request.has_var("_move"):
            from_pos = request.get_integer_input_mandatory("_move")
            to_pos = request.get_integer_input_mandatory("_index")
            connection = connections[from_pos]
            self._add_change(
                "move-ldap-connection",
                _("Changed position of LDAP connection %s to %d") %
                (connection["id"], to_pos),
            )
            del connections[from_pos]  # make to_pos now match!
            connections[to_pos:to_pos] = [connection]
            save_connection_config(connections)

        return redirect(self.mode_url())
Ejemplo n.º 2
0
def _confirm(html_title, message):
    if not request.has_var("_do_confirm") and not request.has_var(
            "_do_actions"):
        # TODO: get the breadcrumb from all call sites
        wato_html_head(title=html_title, breadcrumb=Breadcrumb())
    confirm_options = [(_("Confirm"), "_do_confirm")]
    return confirm_with_preview(message, confirm_options)
Ejemplo n.º 3
0
    def action(self) -> ActionResult:
        if not transactions.check_transaction():
            return redirect(mode_url("tags"))

        if request.has_var("_delete"):
            return self._delete_tag_group()

        if request.has_var("_del_aux"):
            return self._delete_aux_tag()

        if request.var("_move"):
            return self._move_tag_group()

        return redirect(mode_url("tags"))
Ejemplo n.º 4
0
    def _get_search_vars(self) -> HTTPVariables:
        search_vars = {}

        if request.has_var("host_search_host"):
            search_vars[
                "host_search_host"] = request.get_ascii_input_mandatory(
                    "host_search_host")

        for varname, value in request.itervars(prefix="host_search_change_"):
            if html.get_checkbox(varname) is False:
                continue

            search_vars[varname] = value

            attr_ident = varname.split("host_search_change_", 1)[1]

            # The URL variable naming scheme is not clear. Try to match with "attr_" prefix
            # and without. We should investigate and clean this up.
            attr_prefix = "host_search_attr_%s" % attr_ident
            search_vars.update(request.itervars(prefix=attr_prefix))
            attr_prefix = "host_search_%s" % attr_ident
            search_vars.update(request.itervars(prefix=attr_prefix))

        for varname, value in request.itervars():
            if varname.startswith(("_", "host_search_")) or varname == "mode":
                continue
            search_vars[varname] = value

        search_vars["mode"] = "folder"

        return list(search_vars.items())
Ejemplo n.º 5
0
 def _action(
     self, cmdtag: str, spec: str, row: dict, row_index: int, num_rows: int
 ) -> CommandActionResult:
     if request.has_var("_delete_crash_reports"):
         commands = [("DEL_CRASH_REPORT;%s" % row["crash_id"])]
         return commands, _("remove")
     return None
Ejemplo n.º 6
0
def show_log_list():
    title = _("All problematic logfiles")
    breadcrumb = make_simple_page_breadcrumb(
        mega_menu_registry.menu_monitoring(), title)
    make_header(html, title, breadcrumb, _log_list_page_menu(breadcrumb))

    if request.has_var("_ack") and not request.var("_do_actions") == _("No"):
        do_log_ack(site=None, host_name=None, file_name=None)
        return

    for site, host_name, logs in all_logs():
        if not logs:
            continue

        all_logs_empty = not any(
            parse_file(site, host_name, file_name) for file_name in logs)

        if all_logs_empty:
            continue  # Logfile vanished

        html.h3(
            HTMLWriter.render_a(
                host_name,
                href=makeuri(
                    request,
                    [("site", site), ("host", host_name)],
                ),
            ),
            class_="table",
        )
        list_logs(site, host_name, logs)
    html.footer()
Ejemplo n.º 7
0
def _page_not_found() -> Response:
    # TODO: This is a page handler. It should not be located in generic application
    # object. Move it to another place
    if request.has_var("_plain_error"):
        html.write_text(_("Page not found"))
    else:
        title = _("Page not found")
        make_header(
            html,
            title,
            Breadcrumb([
                BreadcrumbItem(
                    title="Nowhere",
                    url=None,
                ),
                BreadcrumbItem(
                    title=title,
                    url="javascript:document.location.reload(false)",
                ),
            ]),
        )
        html.show_error(_("This page was not found. Sorry."))
    html.footer()

    return response
Ejemplo n.º 8
0
    def page(self) -> PageResult:
        """Determines the hosts to be shown"""
        user.need_permission("general.parent_child_topology")

        topology_settings = TopologySettings()
        if request.var("filled_in"):
            # Parameters from the check_mk filters
            self._update_topology_settings_with_context(topology_settings)
        elif request.var("host_name"):
            # Explicit host_name. Used by icon linking to Topology
            topology_settings.growth_root_nodes = {
                HostName(html.request.get_str_input_mandatory("host_name"))
            }
        else:
            # Default page without further context
            topology_settings.growth_root_nodes = self._get_default_view_hostnames(
                topology_settings.growth_auto_max_nodes
            )

        if request.has_var("topology_settings"):
            # These parameters are usually generated within javascript through user interactions
            try:
                settings_from_var = json.loads(request.get_str_input_mandatory("topology_settings"))
                for key, value in settings_from_var.items():
                    setattr(topology_settings, key, value)
            except (TypeError, ValueError):
                raise MKGeneralException(_("Invalid topology_settings %r") % topology_settings)

        self.show_topology(topology_settings)
Ejemplo n.º 9
0
    def _delete_tag_group(self) -> ActionResult:
        del_id = request.get_item_input(
            "_delete", dict(self._tag_config.get_tag_group_choices()))[1]

        if not request.has_var(
                "_repair") and self._is_cleaning_up_user_tag_group_to_builtin(
                    del_id):
            message: Union[bool, str] = (
                _('Transformed the user tag group "%s" to builtin.') % del_id)
        else:
            message = _rename_tags_after_confirmation(
                self.breadcrumb(), OperationRemoveTagGroup(del_id))
            if message is False:
                return FinalizeRequest(code=200)

        if message:
            self._tag_config.remove_tag_group(del_id)
            try:
                self._tag_config.validate_config()
            except MKGeneralException as e:
                raise MKUserError(None, "%s" % e)
            self._save_tags_and_update_hosts(
                self._tag_config.get_dict_format())
            _changes.add_change(
                "edit-tags",
                _("Removed tag group %s (%s)") % (message, del_id))
            if isinstance(message, str):
                flash(message)
        return redirect(mode_url("tags"))
Ejemplo n.º 10
0
class UserTwoFactorOverview(ABCUserProfilePage):
    def _page_title(self) -> str:
        return _("Two-factor authentication")

    def __init__(self) -> None:
        super().__init__("general.manage_2fa")

    def _action(self) -> None:
        assert user.id is not None
        credentials = load_two_factor_credentials(user.id)

        if credential_id := request.get_ascii_input("_delete"):
            if credential_id not in credentials["webauthn_credentials"]:
                return
            del credentials["webauthn_credentials"][credential_id]
            save_two_factor_credentials(user.id, credentials)
            flash(_("Credential has been deleted"))

        if request.has_var("_backup_codes"):
            codes = make_two_factor_backup_codes()
            credentials["backup_codes"] = [
                pwhashed for _password, pwhashed in codes
            ]
            save_two_factor_credentials(user.id, credentials)
            flash(
                _("The following backup codes have been generated: <ul>%s</ul> These codes are "
                  "displayed only now. Save them securely.") %
                "".join(f"<li><tt>{password}</tt></li>"
                        for password, _pwhashed in codes))
Ejemplo n.º 11
0
def page_api() -> None:
    try:
        if not request.has_var("output_format"):
            response.set_content_type("application/json")
            output_format = "json"
        else:
            output_format = request.get_ascii_input_mandatory(
                "output_format", "json").lower()

        if output_format not in _FORMATTERS:
            response.set_content_type("text/plain")
            raise MKUserError(
                None,
                "Only %s are supported as output formats" %
                " and ".join('"%s"' % f for f in _FORMATTERS),
            )

        # TODO: Add some kind of helper for boolean-valued variables?
        pretty_print = False
        pretty_print_var = request.get_str_input_mandatory(
            "pretty_print", "no").lower()
        if pretty_print_var not in ("yes", "no"):
            raise MKUserError(None, 'pretty_print must be "yes" or "no"')
        pretty_print = pretty_print_var == "yes"

        api_call = _get_api_call()
        _check_permissions(api_call)
        request_object = _get_request(api_call)
        _check_formats(output_format, api_call, request_object)
        _check_request_keys(api_call, request_object)
        resp = _execute_action(api_call, request_object)

    except MKAuthException as e:
        resp = {
            "result_code":
            1,
            "result":
            _("Authorization Error. Insufficent permissions for '%s'") % e,
        }
    except MKException as e:
        resp = {
            "result_code":
            1,
            "result":
            _("Checkmk exception: %s\n%s") %
            (e, "".join(traceback.format_exc())),
        }
    except Exception:
        if active_config.debug:
            raise
        logger.exception("error handling web API call")
        resp = {
            "result_code": 1,
            "result": _("Unhandled exception: %s") % traceback.format_exc(),
        }

    response.set_data(
        _FORMATTERS[output_format][1 if pretty_print else 0](resp))
Ejemplo n.º 12
0
    def action(self) -> ActionResult:
        if not transactions.check_transaction():
            return redirect(self.mode_url())

        if request.has_var("_delete"):
            icon_name = request.var("_delete")
            if icon_name in self._load_custom_icons():
                os.remove(
                    "%s/local/share/check_mk/web/htdocs/images/icons/%s.png" %
                    (cmk.utils.paths.omd_root, icon_name))

        elif request.has_var("_save"):
            vs_upload = self._vs_upload()
            icon_info = vs_upload.from_html_vars("_upload_icon")
            vs_upload.validate_value(icon_info, "_upload_icon")
            self._upload_icon(icon_info)

        return redirect(self.mode_url())
Ejemplo n.º 13
0
    def infos(self) -> SingleInfos:
        # Hack for create mode of dashlet editor. The user first selects a datasource and then the
        # single contexts, the dashlet editor needs to use these information.
        if requested_file_name(request) == "edit_dashlet" and request.has_var(
                "datasource"):
            ds_name = request.get_str_input_mandatory("datasource")
            return list(data_source_registry[ds_name]().infos)  # TODO: Hmmm...

        return self._get_infos_from_view_spec(self._dashlet_spec)
Ejemplo n.º 14
0
    def action(self) -> ActionResult:
        if transactions.transaction_valid():
            if request.has_var("_do_upload"):
                self._upload_csv_file()

            csv_reader = self._open_csv_file()

            if request.var("_do_import"):
                return self._import(csv_reader)
        return None
Ejemplo n.º 15
0
def _werk_table_options_from_request() -> Dict[str, Any]:
    if request.var("show_unack") and not request.has_var("wo_set"):
        return _default_werk_table_options()

    werk_table_options: Dict[str, Any] = {}
    for name, _height, vs, default_value in _werk_table_option_entries():
        value = default_value
        try:
            if request.has_var("wo_set"):
                value = vs.from_html_vars("wo_" + name)
                vs.validate_value(value, "wo_" + name)
        except MKUserError as e:
            html.user_error(e)

        werk_table_options.setdefault(name, value)

    from_date, until_date = Timerange.compute_range(
        werk_table_options["date"]).range
    werk_table_options["date_range"] = from_date, until_date

    return werk_table_options
Ejemplo n.º 16
0
    def page(self):
        html.open_div(class_="diag_host")
        html.open_table()
        html.open_tr()
        html.open_td()

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

        forms.header(_("Host Properties"))

        forms.section(legend=False)

        # The diagnose page shows both snmp variants at the same time
        # We need to analyse the preconfigured community and set either the
        # snmp_community or the snmp_v3_credentials
        vs_dict = {}
        for key, value in self._host.attributes().items():
            if key == "snmp_community" and isinstance(value, tuple):
                vs_dict["snmp_v3_credentials"] = value
                continue
            vs_dict[key] = value

        vs_host = self._vs_host()
        vs_host.render_input("vs_host", vs_dict)
        html.help(vs_host.help())

        forms.end()

        html.open_div(style="margin-bottom:10px")
        html.close_div()

        forms.header(_("Options"))

        value = {}
        forms.section(legend=False)
        vs_rules = self._vs_rules()
        vs_rules.render_input("vs_rules", value)
        html.help(vs_rules.help())
        forms.end()

        # When clicking "Save & Test" on the "Edit host" page, this will be set
        # to immediately execute the tests using the just saved settings
        if request.has_var("_start_on_load"):
            html.final_javascript("cmk.page_menu.form_submit('diag_host', '_save');")

        html.hidden_fields()
        html.end_form()

        html.close_td()
        html.open_td(style="padding-left:10px;")

        self._show_diagnose_output()
Ejemplo n.º 17
0
    def _show_view_as_dashlet(self, view_spec: ViewSpec):
        html.add_body_css_class("view")
        html.open_div(id_="dashlet_content_wrapper")

        is_reload = request.has_var("_reload")

        view_display_options = "SIXLW"
        if not is_reload:
            view_display_options += "HR"

        request.set_var("display_options", view_display_options)
        request.set_var("_display_options", view_display_options)
        html.add_body_css_class("dashlet")

        # Need to be loaded before processing the painter_options below.
        # TODO: Make this dependency explicit
        display_options.load_from_html(request, html)

        painter_options = PainterOptions.get_instance()
        painter_options.load(self._dashlet_spec["name"])

        # Here the linked view default context has the highest priority
        # linkedview default>dashlet>url active filter> dashboard. However views
        # have the "show_filters" default to prefill the filtermenu with empty
        # valued filters(UX). Those need to be cleared out. Otherwise those
        # empty filters are the highest priority filters and the user can never
        # filter the view.

        view_context = {
            filtername: filtervalues
            for filtername, filtervalues in view_spec["context"].items() if {
                var: value
                for var, value in filtervalues.items()
                # These are the filters request variables. Keep set values
                # For the TriStateFilters unset == ignore == "-1"
                # all other cases unset is an empty string
                if (var.startswith("is_") and value != "-1"
                    )  # TriState filters except ignore
                or (not var.startswith("is_") and value
                    )  # Rest of filters with some value
            }
        }
        context = visuals.get_merged_context(self.context, view_context)

        view = views.View(self._dashlet_spec["name"], view_spec, context)
        view.row_limit = views.get_limit()
        view.only_sites = visuals.get_only_sites_from_context(context)
        view.user_sorters = views.get_user_sorters()

        views.process_view(views.GUIViewRenderer(view, show_buttons=False))

        html.close_div()
Ejemplo n.º 18
0
def render_unacknowleged_werks():
    werks = unacknowledged_incompatible_werks()
    if werks and not request.has_var("show_unack"):
        html.open_div(class_=["warning"])
        html.write_text(
            _("<b>Warning:</b> There are %d unacknowledged incompatible werks:"
              ) % len(werks))
        html.br()
        html.br()
        html.a(
            _("Show unacknowledged incompatible werks"),
            href=makeuri_contextless(request, [("show_unack", "1"),
                                               ("wo_compatibility", "3")]),
        )
        html.close_div()
Ejemplo n.º 19
0
def selection_id() -> str:
    """Generates a selection id or uses the given one"""
    if not request.has_var("selection"):
        sel_id = utils.gen_id()
        request.set_var("selection", sel_id)
        return sel_id

    sel_id = request.get_str_input_mandatory("selection")

    # Avoid illegal file access by introducing .. or /
    if not re.match("^[-0-9a-zA-Z]+$", sel_id):
        new_id = utils.gen_id()
        request.set_var("selection", new_id)
        return new_id
    return sel_id
Ejemplo n.º 20
0
def show_host_log_list(site, host_name):
    title = _("Logfiles of host %s") % host_name
    breadcrumb = _host_log_list_breadcrumb(host_name, title)
    make_header(html, title, breadcrumb,
                _host_log_list_page_menu(breadcrumb, site, host_name))

    if request.has_var("_ack") and not request.var("_do_actions") == _("No"):
        do_log_ack(site, host_name, file_name=None)
        return

    html.open_table(class_=["data"])
    list_logs(site, host_name, logfiles_of_host(site, host_name))
    html.close_table()

    html.footer()
Ejemplo n.º 21
0
    def page(self):
        if not user.may("wato.automation"):
            raise MKAuthException(
                _("This account has no permission for automation."))

        response.set_content_type("text/plain")
        _set_version_headers()

        # Parameter was added with 1.5.0p10
        if not request.has_var("_version"):
            raise MKGeneralException(
                _("Your central site is incompatible with this remote site"))

        # - _version and _edition_short were added with 1.5.0p10 to the login call only
        # - x-checkmk-version and x-checkmk-edition were added with 2.0.0p1
        # Prefer the headers and fall back to the request variables for now.
        central_version = (request.headers["x-checkmk-version"]
                           if "x-checkmk-version" in request.headers else
                           request.get_ascii_input_mandatory("_version"))
        central_edition_short = (
            request.headers["x-checkmk-edition"]
            if "x-checkmk-edition" in request.headers else
            request.get_ascii_input_mandatory("_edition_short"))

        if not compatible_with_central_site(
                central_version,
                central_edition_short,
                cmk_version.__version__,
                cmk_version.edition().short,
        ):
            raise MKGeneralException(
                _("Your central site (Version: %s, Edition: %s) is incompatible with this "
                  "remote site (Version: %s, Edition: %s)") % (
                      central_version,
                      central_edition_short,
                      cmk_version.__version__,
                      cmk_version.edition().short,
                  ))

        response.set_data(
            repr({
                "version": cmk_version.__version__,
                "edition_short": cmk_version.edition().short,
                "login_secret": _get_login_secret(create_on_demand=True),
            }))
Ejemplo n.º 22
0
    def action(self) -> ActionResult:
        if self._may_edit_config() and request.has_var("_delete"):
            key_id_as_str = request.var("_delete")
            if key_id_as_str is None:
                raise Exception("cannot happen")
            key_id = int(key_id_as_str)
            keys = self.key_store.load()
            if key_id not in keys:
                return None

            key = keys[key_id]

            if self._key_in_use(key_id, key):
                raise MKUserError("", _("This key is still used."))

            del keys[key_id]
            self._log_delete_action(key_id, key)
            self.key_store.save(keys)
        return None
Ejemplo n.º 23
0
def confirm_with_preview(msg: Union[str, HTML],
                         confirm_options: List[Tuple[str, str]],
                         method: str = "POST") -> Optional[bool]:
    """Show a confirm dialog to the user

    BE AWARE: In case you just want to have some action confirmed by the user, you
    should use the javascript powere confirm dialg (make_confirm, add_confirm_on_submit, ...).

    This method is used only in places where we explicitly need to show important information to the
    user before he can decide whether or not to confirm the action.

    The confirm dialog is normally not a dialog which need to be protected by a transid itselfs. It
    is only a intermediate step to the real action But there are use cases where the confirm dialog
    is used during rendering a normal page, for example when deleting a dashlet from a dashboard. In
    such cases, the transid must be added by the confirm dialog.
    """
    if request.var("_do_actions") == _("Cancel"):
        # User has pressed "Cancel", now invalidate the unused transid
        transactions.check_transaction()
        return None  # None --> "Cancel"

    if not any(
            request.has_var(varname) for _title, varname in confirm_options):
        mobile = is_mobile(request, response)
        if mobile:
            html.open_center()
        html.open_div(class_="really")
        html.write_text(msg)
        html.begin_form("confirm", method=method, add_transid=False)
        html.hidden_fields(add_action_vars=True)
        for title, varname in confirm_options:
            html.button(varname, title, "really")
        html.button("_do_actions", _("Cancel"))
        html.end_form()
        html.close_div()
        if mobile:
            html.close_center()

        return False  # False --> "Dialog shown, no answer yet"

    # Now check the transaction. True: "Yes", None --> Browser reload of "yes" page
    return True if transactions.check_transaction() else None
Ejemplo n.º 24
0
    def page(self) -> None:
        row = self._get_crash_row()
        crash_info = self._get_crash_info(row)

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

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

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

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

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

        html.footer()
Ejemplo n.º 25
0
    def page_menu(self, breadcrumb: Breadcrumb) -> PageMenu:
        if not request.has_var("file_id"):
            return make_simple_form_page_menu(
                _("Hosts"),
                breadcrumb,
                form_name="upload",
                button_name="_do_upload",
                save_title=_("Upload"),
            )

        # preview phase, after first upload
        return PageMenu(
            dropdowns=[
                PageMenuDropdown(
                    name="actions",
                    title=_("Actions"),
                    topics=[
                        PageMenuTopic(
                            title=_("Actions"),
                            entries=[
                                PageMenuEntry(
                                    title=_("Update preview"),
                                    icon_name="update",
                                    item=make_form_submit_link("preview", "_do_preview"),
                                    is_shortcut=True,
                                    is_suggested=True,
                                ),
                                PageMenuEntry(
                                    title=_("Import"),
                                    icon_name="save",
                                    item=make_form_submit_link("preview", "_do_import"),
                                    is_shortcut=True,
                                    is_suggested=True,
                                ),
                            ],
                        ),
                    ],
                ),
            ],
            breadcrumb=breadcrumb,
        )
Ejemplo n.º 26
0
    def render_input(self, varprefix: str, value: dict[str, Any]) -> None:
        # The display mode differs when the valuespec is activated
        vars_copy = dict(request.itervars())

        # The timeperiod mode can be set by either the GUI switch or by the value itself
        # GUI switch overrules the information stored in the value
        if request.has_var(self.tp_toggle_var):
            is_active = self._is_switched_on()
        else:
            is_active = self.is_active(value)

        # Set the actual used mode
        html.hidden_field(self.tp_current_mode, "%d" % is_active)

        vars_copy[self.tp_toggle_var] = "%d" % (not is_active)

        url_vars: HTTPVariables = []
        url_vars += vars_copy.items()
        toggle_url = makeuri(request, url_vars)

        if is_active:
            value = self._get_timeperiod_value(value)
            self._get_timeperiod_valuespec().render_input(varprefix, value)
            html.buttonlink(
                toggle_url,
                _("Disable timespecific parameters"),
                class_=["toggle_timespecific_parameter"],
            )
        else:
            value = self._get_timeless_value(value)
            self._enclosed_valuespec.render_input(varprefix, value)
            html.buttonlink(
                toggle_url,
                _("Enable timespecific parameters"),
                class_=["toggle_timespecific_parameter"],
            )
Ejemplo n.º 27
0
    def _get_id(self):
        if not request.has_var("edit"):
            return None

        return request.get_item_input(
            "edit", dict(self._tag_config.aux_tag_list.get_choices()))[1]
Ejemplo n.º 28
0
    def _write_table(
        self,
        rows: TableRows,
        num_rows_unlimited: int,
        actions_enabled: bool,
        actions_visible: bool,
        search_term: Optional[str],
    ) -> None:
        if not self.options["omit_update_header"]:
            row_info = _("1 row") if len(
                rows) == 1 else _("%d rows") % num_rows_unlimited
            html.javascript("cmk.utils.update_row_info(%s);" %
                            json.dumps(row_info))

        table_id = self.id

        num_cols = self._get_num_cols(rows)

        empty_columns = self._get_empty_columns(rows, num_cols)
        if self.options["omit_empty_columns"]:
            num_cols -= len([v for v in empty_columns if v])

        html.open_table(class_=["data", "oddeven"] + self.css)

        # If we have no group headers then paint the headers now
        if self.rows and not isinstance(self.rows[0], GroupHeader):
            self._render_headers(
                actions_enabled,
                actions_visible,
                empty_columns,
            )

        if actions_enabled and actions_visible:
            html.open_tr(class_=["data", "even0", "actions"])
            html.open_td(colspan=num_cols)
            if not html.in_form():
                html.begin_form("%s_actions" % table_id)

            if request.has_var("_%s_sort" % table_id):
                html.open_div(class_=["sort"])
                html.button("_%s_reset_sorting" % table_id, _("Reset sorting"))
                html.close_div()

            if not html.in_form():
                html.begin_form("%s_actions" % table_id)

            html.hidden_fields()
            html.end_form()
            html.close_tr()

        for nr, row in enumerate(rows):
            # Intermediate header
            if isinstance(row, GroupHeader):
                # Show the header only, if at least one (non-header) row follows
                if nr < len(rows) - 1 and not isinstance(
                        rows[nr + 1], GroupHeader):
                    html.open_tr(class_="groupheader")
                    html.open_td(colspan=num_cols)
                    html.h3(row.title)
                    html.close_td()
                    html.close_tr()

                    self._render_headers(actions_enabled, actions_visible,
                                         empty_columns)
                continue

            oddeven_name = "even" if nr % 2 == 0 else "odd"
            class_ = ["data", "%s%d" % (oddeven_name, row.state)]

            if isinstance(row.css, list):
                class_.extend([c for c in row.css if c is not None])
            elif row.css is not None:
                class_.append(row.css)

            html.open_tr(class_=class_,
                         id_=row.id_,
                         onmouseover=row.onmouseover,
                         onmouseout=row.onmouseout)
            for col_index, cell in enumerate(row.cells):
                if self.options["omit_empty_columns"] and empty_columns[
                        col_index]:
                    continue

                html.td(cell.content, class_=cell.css, colspan=cell.colspan)
            html.close_tr()

        if not rows and search_term:
            html.open_tr(class_=["data", "odd0", "no_match"])
            html.td(
                _("Found no matching rows. Please try another search term."),
                colspan=num_cols)
            html.close_tr()

        html.close_table()
Ejemplo n.º 29
0
def plain_error() -> bool:
    """Webservice functions may decide to get a normal result code
    but a text with an error message in case of an error"""
    return request.has_var("_plain_error") or requested_file_name(
        request) == "webapi"
Ejemplo n.º 30
0
def fail_silently() -> bool:
    """Ajax-Functions want no HTML output in case of an error but
    just a plain server result code of 500"""
    return request.has_var("_ajaxid")