def query_limit_exceeded_warn(limit: Optional[int], user_config: LoggedInUser) -> None: """Compare query reply against limits, warn in the GUI about incompleteness""" text = HTML(_("Your query produced more than %d results. ") % limit) if request.get_ascii_input("limit", "soft") == "soft" and user_config.may( "general.ignore_soft_limit" ): text += HTMLWriter.render_a( _("Repeat query and allow more results."), target="_self", href=makeuri(request, [("limit", "hard")]), ) elif request.get_ascii_input("limit") == "hard" and user_config.may( "general.ignore_hard_limit" ): text += HTMLWriter.render_a( _("Repeat query without limit."), target="_self", href=makeuri(request, [("limit", "none")]), ) text += escaping.escape_to_html_permissive( " " + _("<b>Note:</b> the shown results are incomplete and do not reflect the sort order.") ) html.show_warning(text)
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"))
def inpage_search_form(mode: Optional[str] = None, default_value: str = "") -> None: form_name = "inpage_search_form" reset_button_id = "%s_reset" % form_name was_submitted = request.get_ascii_input("filled_in") == form_name html.begin_form(form_name, add_transid=False) html.text_input( "search", size=32, default_value=default_value, placeholder=_("Filter"), required=True, title="", ) html.hidden_fields() if mode: html.hidden_field("mode", mode, add_var=True) reset_url = request.get_ascii_input_mandatory("reset_url", requested_file_with_query(request)) html.hidden_field("reset_url", reset_url, add_var=True) html.button("submit", "", cssclass="submit", help_=_("Apply")) html.buttonlink(reset_url, "", obj_id=reset_button_id, title=_("Reset")) html.end_form() html.javascript( "cmk.page_menu.inpage_search_init(%s, %s)" % (json.dumps(reset_button_id), json.dumps(was_submitted)) )
def __init__( self, table_id: Optional[str] = None, title: Optional[HTMLContent] = None, searchable: bool = True, sortable: bool = True, foldable: Foldable = Foldable.NOT_FOLDABLE, limit: Union[None, int, Literal[False]] = None, output_format: str = "html", omit_if_empty: bool = False, omit_empty_columns: bool = False, omit_headers: bool = False, omit_update_header: bool = False, empty_text: Optional[str] = None, help: Optional[str] = None, # pylint: disable=redefined-builtin css: Optional[str] = None, isopen: bool = True, ): super().__init__() self.next_func = lambda: None self.next_header: Optional[str] = None # Use our pagename as table id if none is specified table_id = table_id if table_id is not None else requested_file_name( request) assert table_id is not None # determine row limit if limit is None: limit = active_config.table_row_limit if request.get_ascii_input( "limit") == "none" or output_format != "html": limit = None self.id = table_id self.title = title self.rows: TableRows = [] self.limit = limit self.limit_reached = False self.limit_hint: Optional[int] = None self.headers: List[TableHeader] = [] self.options = { "collect_headers": False, # also: True, "finished" "omit_if_empty": omit_if_empty, "omit_empty_columns": omit_empty_columns, "omit_headers": omit_headers, "omit_update_header": omit_update_header, "searchable": searchable, "sortable": sortable, "foldable": foldable, "output_format": output_format, # possible: html, csv, fetch } self.empty_text = empty_text if empty_text is not None else _( "No entries.") self.help = help self.css = [] if css is None else [css] self.mode = "row" self.isopen: Final = isopen
def _from_vars(self) -> None: edit_group = request.get_ascii_input("edit") # missing -> new group self._name = GroupName(edit_group) if edit_group else None self._new = self._name is None if self._new: clone_group = request.get_ascii_input("clone") if clone_group: self._name = GroupName(clone_group) self.group = self._get_group(self._name) else: self.group = {} else: assert self._name is not None self.group = self._get_group(self._name) self.group.setdefault("alias", self._name)
def _evaluate_user_opts(self) -> Tuple[TableRows, bool, Optional[str]]: assert self.id is not None table_id = self.id rows = self.rows search_term = None actions_enabled = self.options["searchable"] or self.options["sortable"] if not actions_enabled: return rows, False, None table_opts = user.tableoptions.setdefault(table_id, {}) # Handle the initial visibility of the actions actions_visible = table_opts.get("actions_visible", False) if request.get_ascii_input("_%s_actions" % table_id): actions_visible = request.get_ascii_input("_%s_actions" % table_id) == "1" table_opts["actions_visible"] = actions_visible if self.options["searchable"]: search_term = request.get_str_input_mandatory("search", "") # Search is always lower case -> case insensitive search_term = search_term.lower() if search_term: request.set_var("search", search_term) rows = _filter_rows(rows, search_term) if request.get_ascii_input("_%s_reset_sorting" % table_id): request.del_var("_%s_sort" % table_id) if "sort" in table_opts: del table_opts["sort"] # persist if self.options["sortable"]: # Now apply eventual sorting settings sort = self._get_sort_column(table_opts) if sort is not None: request.set_var("_%s_sort" % table_id, sort) table_opts["sort"] = sort # persist sort_col, sort_reverse = map(int, sort.split(",", 1)) rows = _sort_rows(rows, sort_col, sort_reverse) if actions_enabled: user.save_tableoptions() return rows, actions_visible, search_term
def page(self) -> None: assert user.id is not None html.render_headfoot = False html.add_body_css_class("login") html.add_body_css_class("two_factor") make_header(html, _("Two-factor authentication"), Breadcrumb(), javascripts=[]) html.open_div(id_="login") html.open_div(id_="login_window") html.open_a(href="https://checkmk.com") html.img( src=theme.detect_icon_path(icon_name="logo", prefix="mk-"), id_="logo", class_="custom" if theme.has_custom_logo() else None, ) html.close_a() if not is_two_factor_login_enabled(user.id): raise MKGeneralException( _("Two-factor authentication not enabled")) html.begin_form("two_factor_login", method="POST", add_transid=False, action="user_login_two_factor.py") html.prevent_password_auto_completion() html.hidden_field( "_origtarget", origtarget := request.get_url_input("_origtarget", "index.py")) if backup_code := request.get_ascii_input("_backup_code"): if is_two_factor_backup_code_valid(user.id, backup_code): set_two_factor_completed() raise HTTPRedirect(origtarget)
def _init_host(self) -> CREHost: clonename = request.get_ascii_input("clone") if not clonename: return self._init_new_host_object() if not Folder.current().has_host(clonename): raise MKUserError( "host", _("You called this page with an invalid host name.")) if not user.may("wato.clone_hosts"): raise MKAuthException( _("Sorry, you are not allowed to clone hosts.")) host = Folder.current().load_host(clonename) self._verify_host_type(host) return host
def _from_vars(self) -> None: ident = request.get_ascii_input("ident") if ident is not None: try: entry = self._store.filter_editable_entries( self._store.load_for_reading())[ident] except KeyError: raise MKUserError( "ident", _("This %s does not exist.") % self._mode_type.name_singular()) self._new = False self._ident: Optional[str] = ident self._entry = entry return clone = request.get_ascii_input("clone") if clone is not None: try: entry = self._store.filter_editable_entries( self._store.load_for_reading())[clone] except KeyError: raise MKUserError( "clone", _("This %s does not exist.") % self._mode_type.name_singular()) self._new = True self._ident = None self._entry = copy.deepcopy(entry) return self._new = True self._ident = None self._entry = {}
def _from_vars(self): self._name = request.get_ascii_input("edit") # missing -> new custom attr self._new = self._name is None # TODO: Inappropriate Intimacy: custom host attributes should not now about # custom user attributes and vice versa. The only reason they now about # each other now is that they are stored in one file. self._all_attrs = load_custom_attrs_from_mk_file(lock=transactions.is_transaction()) if not self._new: matching_attrs = [a for a in self._attrs if a["name"] == self._name] if not matching_attrs: raise MKUserError(None, _("The attribute does not exist.")) self._attr: Dict[str, Any] = matching_attrs[0] else: self._attr = {}
def _from_vars(self): self._connection_id = request.get_ascii_input("id") self._connection_cfg = {} self._connections = load_connection_config( lock=transactions.is_transaction()) if self._connection_id is None: clone_id = request.var("clone") if clone_id is not None: self._connection_cfg = self._get_connection_cfg_and_index( clone_id)[0] self._new = True return self._new = False self._connection_cfg, self._connection_nr = self._get_connection_cfg_and_index( self._connection_id)
def _show_form(self) -> None: assert user.id is not None users = userdb.load_users() change_reason = request.get_ascii_input("reason") if change_reason == "expired": html.p(_("Your password is too old, you need to choose a new password.")) elif change_reason == "enforced": html.p(_("You are required to change your password before proceeding.")) user_spec = users.get(user.id) if user_spec is None: html.show_warning(_("Sorry, your user account does not exist.")) html.footer() return locked_attributes = userdb.locked_attributes(user_spec.get("connector")) if "password" in locked_attributes: raise MKUserError( "cur_password", _("You can not change your password, because it is " "managed by another system."), ) html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(self._page_title()) forms.section(_("Current Password")) html.password_input("cur_password", autocomplete="new-password") forms.section(_("New Password")) html.password_input("password", autocomplete="new-password") forms.section(_("New Password Confirmation")) html.password_input("password2", autocomplete="new-password") forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def action(self) -> ActionResult: if not transactions.transaction_valid(): return None action_var = request.get_str_input("_action") if action_var is None: return None if action_var != "delete": return self._handle_custom_action(action_var) if not transactions.check_transaction(): return redirect(mode_url(self._mode_type.list_mode_name())) entries = self._store.load_for_modification() ident = request.get_ascii_input("_delete") if ident not in entries: raise MKUserError( "_delete", _("This %s does not exist.") % self._mode_type.name_singular()) if ident not in self._store.filter_editable_entries(entries): raise MKUserError( "_delete", _("You are not allowed to delete this %s.") % self._mode_type.name_singular(), ) self._validate_deletion(ident, entries[ident]) entry = entries.pop(ident) self._add_change( action="delete", text=_("Removed the %s '%s'") % (self._mode_type.name_singular(), ident), affected_sites=self._mode_type.affected_sites(entry), ) self._store.save(entries) flash(_("The %s has been deleted.") % self._mode_type.name_singular()) return redirect(mode_url(self._mode_type.list_mode_name()))
def _from_vars(self) -> None: self._checkmk_config_files_map = get_checkmk_config_files_map() self._checkmk_log_files_map = get_checkmk_log_files_map() self._collect_dump = bool(request.get_ascii_input("_collect_dump")) self._diagnostics_parameters = self._get_diagnostics_parameters() self._job = DiagnosticsDumpBackgroundJob()
def _render_headers(self, actions_enabled: bool, actions_visible: bool, empty_columns: List[bool]) -> None: if self.options["omit_headers"]: return table_id = self.id html.open_tr() first_col = True for nr, header in enumerate(self.headers): if self.options["omit_empty_columns"] and empty_columns[nr]: continue if header.help_txt: header_title: HTML = HTMLWriter.render_span( header.title, title=header.help_txt) else: header_title = header.title if not isinstance(header.css, list): css_class: "CSSSpec" = [header.css] else: css_class = header.css assert isinstance(css_class, list) css_class = [("header_%s" % c) for c in css_class if c is not None] if not self.options["sortable"] or not header.sortable: html.open_th(class_=css_class) else: css_class.insert(0, "sort") reverse = 0 sort = request.get_ascii_input("_%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 = makeactionuri(request, transactions, [("_%s_sort" % table_id, "%d,%d" % (nr, reverse))]) html.open_th( class_=css_class, title=_("Sort by %s") % header.title, onclick="location.href='%s'" % action_uri, ) # Add the table action link if first_col: first_col = False if actions_enabled: if not header_title: header_title = HTML( " " ) # 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( makeuri(request, [("_%s_actions" % table_id, state)]), help_txt, img, cssclass="toggle_actions", ) html.span(header_title) html.close_div() else: html.write_text(header_title) else: html.write_text(header_title) html.close_th() html.close_tr()
def _get_sort_column(self, table_opts: Dict[str, Any]) -> Optional[str]: return request.get_ascii_input("_%s_sort" % self.id, table_opts.get("sort"))
def get_request(self) -> SiteRequest: ascii_input = request.get_ascii_input("request") if ascii_input is None: raise MKUserError("request", _('The parameter "%s" is missing.') % "request") return SiteRequest.deserialize(ast.literal_eval(ascii_input))
def _localize_request() -> None: user_language = request.get_ascii_input("lang", user.language) set_language_cookie(request, response, user_language) cmk.gui.i18n.localize(user_language)