def page(self): html.help( _( "The renaming of hosts is a complex operation since a host's name is being " "used as a unique key in various places. It also involves stopping and starting " "of the monitoring core. You cannot rename a host while you have pending changes." ) ) html.begin_form("rename_host", method="POST") html.add_confirm_on_submit( "rename_host", _( "Are you sure you want to rename the host <b>%s</b>? " "This involves a restart of the monitoring core!" ) % (self._host.name()), ) forms.header(_("Rename host %s") % self._host.name()) forms.section(_("Current name")) html.write_text(self._host.name()) forms.section(_("New name")) html.text_input("newname", "") forms.end() html.set_focus("newname") html.hidden_fields() html.end_form()
def page_login(): title = _("Check_MK Mobile") mobile_html_head(title) jqm_page_header(title, id_="login") html.div(_("Welcome to Check_MK Mobile."), id_="loginhead") html.begin_form("login", method='POST', add_transid=False) # Keep information about original target URL origtarget = html.request.var('_origtarget', '') if not origtarget and not html.myfile == 'login': origtarget = html.request.requested_url html.hidden_field('_origtarget', html.attrencode(origtarget)) html.text_input("_username", label=_("Username:"******"_password", size=None, label=_("Password:"******"_login", _('Login')) html.set_focus("_username") html.end_form() html.open_div(id_="loginfoot") html.img("themes/classic/images/logo_cmk_small.png", class_="logomk") html.div(HTML( _("© <a target=\"_blank\" href=\"https://checkmk.com\">tribe29 GmbH</a>" )), class_="copyright") jqm_page_footer() mobile_html_foot()
def page_login() -> None: title = _("Check_MK Mobile") mobile_html_head(title) jqm_page_header(title, id_="login") html.div(_("Welcome to Check_MK Mobile."), id_="loginhead") html.begin_form("login", method='POST', add_transid=False) # Keep information about original target URL default_origtarget = "index.py" if html.myfile in ["login", "logout" ] else html.makeuri([]) origtarget = html.get_url_input("_origtarget", default_origtarget) html.hidden_field('_origtarget', escaping.escape_attribute(origtarget)) html.text_input("_username", label=_("Username:"******"username") html.password_input("_password", size=None, label=_("Password:"******"current-password") html.br() html.button("_login", _('Login')) html.set_focus("_username") html.end_form() html.open_div(id_="loginfoot") html.img("themes/classic/images/logo_cmk_small.png", class_="logomk") html.div(HTML( _("© <a target=\"_blank\" href=\"https://checkmk.com\">tribe29 GmbH</a>" )), class_="copyright") html.close_div() # close content-div html.close_div() html.close_div() # close page-div mobile_html_foot()
def page(self): # Show search form html.begin_form("edit_host", method="POST") html.prevent_password_auto_completion() basic_attributes = [ ( "host_search_host", TextInput( title=_( "Hostname", ) ), "", ), ] html.set_focus("host_search_host") # Attributes configure_attributes( new=False, hosts={}, for_what="host_search", parent=None, varprefix="host_search_", basic_attributes=basic_attributes, ) forms.end() html.hidden_field("host_search", "1") html.hidden_fields() html.end_form()
def page(self): # type: () -> None html.begin_form("group") forms.header(_("Properties")) forms.section(_("Name"), simple=not self._new) html.help( _("The name of the group is used as an internal key. It cannot be " "changed later. It is also visible in the status GUI.")) if self._new: html.text_input("name") html.set_focus("name") else: html.write_text(self._name) html.set_focus("alias") forms.section(_("Alias")) html.help(_("An Alias or description of this group.")) html.text_input("alias", self.group["alias"]) self._show_extra_page_elements() forms.end() html.button("save", _("Save")) html.hidden_fields() html.end_form()
def page(self): self._folder.show_breadcrump() # Show search form html.begin_form("edit_host", method="POST") html.prevent_password_auto_completion() basic_attributes = [ ("host_search_host", TextAscii(title=_("Hostname",)), ""), ] html.set_focus("host_search_host") # Attributes configure_attributes( new=False, hosts={}, for_what="host_search", parent=None, varprefix="host_search_", basic_attributes=basic_attributes, ) # Button forms.end() html.button("_local", _("Search in %s") % self._folder.title(), "submit") html.hidden_field("host_search", "1") html.hidden_fields() html.end_form()
def page(self): # TODO: remove subclass specific things specifict things (everything with _type == 'user') html.begin_form("attr") forms.header(_("Properties")) forms.section(_("Name"), simple=not self._new) html.help( _("The name of the attribute is used as an internal key. It cannot be " "changed later.")) if self._new: html.text_input("name", self._attr.get('name', '')) html.set_focus("name") else: html.write_text(self._name) html.set_focus("title") forms.section(_("Title") + "<sup>*</sup>") html.help(_("The title is used to label this attribute.")) html.text_input("title", self._attr.get('title', '')) forms.section(_('Topic')) html.help( _('The attribute is added to this section in the edit dialog.')) html.dropdown('topic', self._topics, deflt=self._attr.get('topic', self._default_topic)) forms.section(_('Help Text') + "<sup>*</sup>") html.help( _('You might want to add some helpful description for the attribute.' )) html.text_area('help', self._attr.get('help', '')) forms.section(_('Data type')) html.help(_('The type of information to be stored in this attribute.')) if self._new: html.dropdown('type', custom_attr_types(), deflt=self._attr.get('type', '')) else: html.write(dict(custom_attr_types())[self._attr.get('type')]) self._add_extra_form_sections() self._show_in_table_option() forms.section(_('Add to monitoring configuration')) html.help(self._macro_help) html.checkbox('add_custom_macro', self._attr.get('add_custom_macro', False), label=self._macro_label) forms.end() html.show_localization_hint() html.button("save", _("Save")) html.hidden_fields() html.end_form()
def edit_valuespec( vs, # type: Dictionary value, # type: Dict[str, Any] buttontext=None, # type: Optional[Text] method="GET", # type: str varprefix="", # type: str validate=None, # type: Optional[Callable[[Dict[str, Any]], None]] formname="form", # type: str consume_transid=True, # type: bool focus=None # type: Optional[str] ): # type: (...) -> Optional[Dict[str, Any]] if html.request.get_ascii_input( "filled_in") == formname and html.transaction_valid(): if consume_transid: html.check_transaction() messages = [] try: new_value = vs.from_html_vars(varprefix) vs.validate_value(new_value, varprefix) except MKUserError as e: messages.append("%s: %s" % (vs.title(), e.message)) html.add_user_error(e.varname, e.message) if validate and not html.has_user_errors(): try: validate(new_value) except MKUserError as e: messages.append(e.message) html.add_user_error(e.varname, e.message) if messages: html.show_error("".join(["%s<br>\n" % m for m in messages])) else: return new_value html.begin_form(formname, method=method) html.help(vs.help()) vs.render_input(varprefix, value) if buttontext is None: buttontext = _("Save") html.button("save", buttontext) # Should be ignored be hidden_fields, but I do not dare to change it there html.request.del_var("filled_in") html.hidden_fields() if focus: html.set_focus(focus) else: vs.set_focus(varprefix) html.end_form() return None
def search_form(title=None, mode=None, default_value=""): html.begin_form("search", add_transid=False) if title: html.write_text(title + ' ') html.text_input("search", size=32, default_value=default_value) html.hidden_fields() if mode: html.hidden_field("mode", mode, add_var=True) html.set_focus("search") html.write_text(" ") html.button("_do_seach", _("Search")) html.end_form()
def page(self): new = self._folder.name() is None watolib.Folder.current().show_breadcrump() watolib.Folder.current().need_permission("read") if new and watolib.Folder.current().locked(): watolib.Folder.current().show_locking_information() html.begin_form("edit_host", method="POST") # title basic_attributes: List[Tuple[str, ValueSpec, str]] = [ ("title", TextUnicode(title=_("Title")), "" if new else self._folder.title()), ] html.set_focus("title") # folder name (omit this for root folder) if new or not watolib.Folder.current().is_root(): if not config.wato_hide_filenames: basic_attributes += [ ("name", TextAscii( title=_("Internal directory name"), help= _("This is the name of subdirectory where the files and " "other folders will be created. You cannot change this later." ), ), self._folder.name()), ] # Attributes inherited to hosts if new: parent = watolib.Folder.current() myself = None else: parent = watolib.Folder.current().parent() myself = watolib.Folder.current() configure_attributes(new=new, hosts={"folder": myself}, for_what="folder", parent=parent, myself=myself, basic_attributes=basic_attributes) forms.end() if new or not watolib.Folder.current().locked(): html.button("save", _("Save & Finish"), "submit") html.hidden_fields() html.end_form()
def _bulk_actions(self, table, at_least_one_imported, top, withsearch, colspan, show_checkboxes): table.row(collect_headers=False, fixed=True) table.cell(css="bulksearch", colspan=3) if not show_checkboxes: onclick_uri = html.makeuri([('show_checkboxes', '1'), ('selection', weblib.selection_id())]) checkbox_title = _('Show Checkboxes and bulk actions') else: onclick_uri = html.makeuri([('show_checkboxes', '0')]) checkbox_title = _('Hide Checkboxes and bulk actions') html.toggle_button("checkbox_on", show_checkboxes, "checkbox", title=checkbox_title, onclick="location.href=\'%s\'" % onclick_uri, is_context_button=False) if withsearch: html.text_input("search") html.button("_search", _("Search")) html.set_focus("search") table.cell(css="bulkactions", colspan=colspan - 3) html.write_text(' ' + _("Selected hosts:\n")) if not self._folder.locked_hosts(): if config.user.may("wato.manage_hosts"): html.button("_bulk_delete", _("Delete")) if config.user.may("wato.edit_hosts"): html.button("_bulk_edit", _("Edit")) html.button("_bulk_cleanup", _("Cleanup")) if config.user.may("wato.services"): html.button("_bulk_inventory", _("Discovery")) if not self._folder.locked_hosts(): if config.user.may("wato.parentscan"): html.button("_parentscan", _("Parentscan")) if config.user.may("wato.edit_hosts") and config.user.may( "wato.move_hosts"): self._host_bulk_move_to_folder_combo(top) if at_least_one_imported: html.button("_bulk_movetotarget", _("Move to Target Folders"))
def page(self): html.begin_form("random") forms.header(_("Add random hosts")) forms.section(_("Number to create")) html.write_text("%s: " % _("Hosts to create in each folder")) html.text_input("count", default_value="10", cssclass="number") html.set_focus("count") html.br() html.write_text("%s: " % _("Number of folders to create in each level")) html.text_input("folders", default_value="10", cssclass="number") html.br() html.write_text("%s: " % _("Levels of folders to create")) html.text_input("levels", default_value="1", cssclass="number") forms.end() html.hidden_fields() html.end_form()
def page(self): new = self._folder.name() is None watolib.Folder.current().show_breadcrump() watolib.Folder.current().need_permission("read") if new and watolib.Folder.current().locked(): watolib.Folder.current().show_locking_information() html.begin_form("edit_host", method="POST") # title forms.header(_("Title")) forms.section(_("Title")) TextUnicode().render_input("title", self._folder.title()) html.set_focus("title") # folder name (omit this for root folder) if new or not watolib.Folder.current().is_root(): if not config.wato_hide_filenames: forms.section(_("Internal directory name")) if new: html.text_input("name") else: html.write_text(self._folder.name()) html.help( _("This is the name of subdirectory where the files and " "other folders will be created. You cannot change this later." )) # Attributes inherited to hosts if new: parent = watolib.Folder.current() myself = None else: parent = watolib.Folder.current().parent() myself = watolib.Folder.current() configure_attributes(new, {"folder": myself}, "folder", parent, myself) forms.end() if new or not watolib.Folder.current().locked(): html.button("save", _("Save & Finish"), "submit") html.hidden_fields() html.end_form()
def page(self): html.begin_form("random") forms.header(_("Create Random Hosts")) forms.section(_("Number to create")) html.write_text("%s: " % _("Hosts to create in each folder")) html.number_input("count", 10) html.set_focus("count") html.br() html.write_text("%s: " % _("Number of folders to create in each level")) html.number_input("folders", 10) html.br() html.write_text("%s: " % _("Levels of folders to create")) html.number_input("levels", 1) forms.end() html.button("start", _("Start!"), "submit") html.hidden_fields() html.end_form()
def page(self): self._folder.show_breadcrump() # Show search form html.begin_form("edit_host", method="GET") html.prevent_password_auto_completion() forms.header(_("General Properties")) forms.section(_("Hostname")) html.text_input("host_search_host") html.set_focus("host_search_host") # Attributes configure_attributes(False, {}, "host_search", parent=None, varprefix="host_search_") # Button forms.end() html.button("_local", _("Search in %s") % self._folder.title(), "submit") html.hidden_field("host_search", "1") html.hidden_fields() html.end_form()
def _show_login_page(self) -> None: html.set_render_headfoot(False) html.add_body_css_class("login") html.header(config.get_page_heading(), Breadcrumb(), javascripts=[]) default_origtarget = ("index.py" if html.myfile in ["login", "logout"] else makeuri(global_request, [])) origtarget = html.get_url_input("_origtarget", default_origtarget) # Never allow the login page to be opened in the iframe. Redirect top page to login page. # This will result in a full screen login page. html.javascript('''if(top != self) { window.top.location.href = location; }''') # When someone calls the login page directly and is already authed redirect to main page if html.myfile == 'login' and _check_auth(html.request): raise HTTPRedirect(origtarget) html.open_div(id_="login") html.open_div(id_="login_window") html.div("" if "hide_version" in config.login_screen else cmk_version.__version__, id_="version") html.begin_form("login", method='POST', add_transid=False, action='login.py') html.hidden_field('_login', '1') html.hidden_field('_origtarget', origtarget) html.label("%s:" % _('Username'), id_="label_user", class_=["legend"], for_="_username") html.br() html.text_input("_username", id_="input_user") html.label("%s:" % _('Password'), id_="label_pass", class_=["legend"], for_="_password") html.br() html.password_input("_password", id_="input_pass", size=None) if html.has_user_errors(): html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.open_div(id_="button_text") html.button("_login", _('Login')) html.close_div() html.close_div() html.open_div(id_="foot") if config.login_screen.get("login_message"): html.open_div(id_="login_message") html.show_message(config.login_screen["login_message"]) html.close_div() footer: List[Union[HTML, str]] = [] for title, url, target in config.login_screen.get("footer_links", []): footer.append(html.render_a(title, href=url, target=target)) if "hide_version" not in config.login_screen: footer.append("Version: %s" % cmk_version.__version__) footer.append("© %s" % html.render_a( "tribe29 GmbH", href="https://checkmk.com", target="_blank")) html.write(HTML(" - ").join(footer)) if cmk_version.is_raw_edition(): html.br() html.br() html.write( _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">' 'GNU GPL Version 2</a>.') % "https://checkmk.com/gpl.html") html.close_div() html.set_focus('_username') html.hidden_fields() html.end_form() html.close_div() html.footer()
def page(self): search = get_search_expression() html.begin_form("role", method="POST") # ID forms.header(_("Basic properties"), css="wide") forms.section(_("Internal ID"), simple="builtin" in self._role, is_required=True) if self._role.get("builtin"): html.write_text("%s (%s)" % (self._role_id, _("builtin role"))) html.hidden_field("id", self._role_id) else: html.text_input("id", self._role_id) html.set_focus("id") # Alias forms.section(_("Alias")) html.help(_("An alias or description of the role")) html.text_input("alias", self._role.get("alias", ""), size=50) # Based on if not self._role.get("builtin"): forms.section(_("Based on role")) html.help( _("Each user defined role is based on one of the builtin roles. " "When created it will start with all permissions of that role. When due to a software " "update or installation of an addons new permissions appear, the user role will get or " "not get those new permissions based on the default settings of the builtin role it's " "based on.")) role_choices: Choices = [(i, r["alias"]) for i, r in self._roles.items() if r.get("builtin")] html.dropdown("basedon", role_choices, deflt=self._role.get("basedon", "user"), ordered=True) forms.end() html.h2(_("Permissions")) # Permissions base_role_id = self._role.get("basedon", self._role_id) html.help( _("When you leave the permissions at "default" then they get their " "settings from the factory defaults (for builtin roles) or from the " "factory default of their base role (for user define roles). Factory defaults " "may change due to software updates. When choosing another base role, all " "permissions that are on default will reflect the new base role." )) for section in permission_section_registry.get_sorted_sections(): # Now filter by the optional search term filtered_perms = [] for perm in permission_registry.get_sorted_permissions(section): if search and (search not in perm.title.lower() and search not in perm.name.lower()): continue filtered_perms.append(perm) if not filtered_perms: continue forms.header(section.title, isopen=search is not None, css="wide") for perm in filtered_perms: forms.section(perm.title) pvalue = self._role["permissions"].get(perm.name) def_value = base_role_id in perm.defaults choices: Choices = [ ("yes", _("yes")), ("no", _("no")), ("default", _("default (%s)") % (def_value and _("yes") or _("no"))), ] deflt = {True: "yes", False: "no"}.get(pvalue, "default") html.dropdown("perm_" + perm.name, choices, deflt=deflt, style="width: 130px;") html.help(perm.description) forms.end() html.hidden_fields() html.end_form()
def _write_table(self, rows, actions_enabled, actions_visible, search_term): headinfo = _("1 row") if len(rows) == 1 else _("%d rows") % len(rows) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) table_id = self.id num_cols = len(self.headers) empty_columns = self._get_empty_columns(rows, num_cols) 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 self.rows[0][2] != "header": 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 self.options["searchable"]: html.open_div(class_="search") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset search")) html.set_focus("_%s_search" % table_id) html.close_div() if html.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_spec, css, state, _fixed, attrs) in enumerate(rows): if not css and "class_" in attrs: css = attrs.pop("class_") if not css and "class" in attrs: css = attrs.pop("class") # Intermediate header if state == "header": # Show the header only, if at least one (non-header) row follows if nr < len(rows) - 1 and rows[nr + 1][2] != "header": html.open_tr(class_="groupheader") html.open_td(colspan=num_cols) html.open_h3() html.write(row_spec) html.close_h3() html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if (nr - 1) % 2 == 0 else "odd" html.open_tr(class_=[ "data", "%s%d" % (oddeven_name, state), css if css else None ], **attrs) for col_index, (cell_content, css_classes, colspan) in enumerate(row_spec): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.open_td(class_=css_classes if css_classes else None, colspan=colspan if colspan else None) html.write(cell_content) html.close_td() 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()
def _show_host_name(self): forms.section(_("Hostname")) Hostname().render_input("host", "") html.set_focus("host")
def _show_login_page(self) -> None: html.set_render_headfoot(False) html.add_body_css_class("login") html.header(get_page_heading(), Breadcrumb(), javascripts=[]) default_origtarget = ("index.py" if requested_file_name(request) in ["login", "logout"] else makeuri(request, [])) origtarget = request.get_url_input("_origtarget", default_origtarget) # Never allow the login page to be opened in the iframe. Redirect top page to login page. # This will result in a full screen login page. html.javascript("""if(top != self) { window.top.location.href = location; }""") # When someone calls the login page directly and is already authed redirect to main page if requested_file_name(request) == "login" and _check_auth(request): raise HTTPRedirect(origtarget) 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() html.begin_form("login", method="POST", add_transid=False, action="login.py") html.hidden_field("_login", "1") html.hidden_field("_origtarget", origtarget) html.label("%s:" % _("Username"), id_="label_user", class_=["legend"], for_="_username") html.br() html.text_input("_username", id_="input_user") html.label("%s:" % _("Password"), id_="label_pass", class_=["legend"], for_="_password") html.br() html.password_input("_password", id_="input_pass", size=None) if user_errors: html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.open_div(id_="button_text") html.button("_login", _("Login"), cssclass="hot") html.close_div() html.close_div() html.open_div(id_="foot") if config.login_screen.get("login_message"): html.open_div(id_="login_message") html.show_message(config.login_screen["login_message"]) html.close_div() footer: List[HTML] = [] for title, url, target in config.login_screen.get("footer_links", []): footer.append(html.render_a(title, href=url, target=target)) if "hide_version" not in config.login_screen: footer.append(escape_html("Version: %s" % cmk_version.__version__)) footer.append( HTML("© %s" % html.render_a( "tribe29 GmbH", href="https://tribe29.com", target="_blank"))) html.write_html(HTML(" - ").join(footer)) if cmk_version.is_raw_edition(): html.br() html.br() html.write_text( _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">' "GNU GPL Version 2</a>.") % "https://checkmk.com/gpl.html") html.close_div() html.set_focus("_username") html.hidden_fields() html.end_form() html.close_div() html.footer()
def _write_table(self, rows: TableRows, num_rows_unlimited: int, actions_enabled: bool, actions_visible: bool, search_term: Optional[str]) -> None: headinfo = _("1 row") if len( rows) == 1 else _("%d rows") % num_rows_unlimited html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) 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 self.options["searchable"]: html.open_div(class_="search") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset search")) html.set_focus("_%s_search" % table_id) html.close_div() if html.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.open_h3() html.write(row.title) html.close_h3() html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if (nr - 1) % 2 == 0 else "odd" class_ = ["data", "%s%d" % (oddeven_name, row.state)] if row.css: class_.append(row.css) else: for k in ["class_", "class"]: if k in row.row_attributes: cls_spec = cast(CSSSpec, row.row_attributes.pop(k)) if isinstance(cls_spec, list): class_.extend( [c for c in cls_spec if c is not None]) elif cls_spec is not None: class_.append(cls_spec) html.open_tr(class_=class_, **row.row_attributes) for col_index, cell in enumerate(row.cells): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.open_td(class_=cell.css, colspan=cell.colspan) html.write(cell.content) html.close_td() 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()
def page(self): # Show outcome of host validation. Do not validate new hosts errors = None if self._mode == "edit": errors = (watolib.validate_all_hosts([self._host.name()]).get( self._host.name(), []) + self._host.validation_errors()) if errors: html.open_div(class_="info") html.open_table(class_="validationerror", boder="0", cellspacing="0", cellpadding="0") html.open_tr() html.open_td(class_="img") html.icon("validation_error") html.close_td() html.open_td() html.open_p() html.h3(_("Warning: This host has an invalid configuration!")) html.open_ul() for error in errors: html.li(error) html.close_ul() html.close_p() if html.form_submitted(): html.br() html.b(_("Your changes have been saved nevertheless.")) html.close_td() html.close_tr() html.close_table() html.close_div() lock_message = "" locked_hosts = watolib.Folder.current().locked_hosts() if locked_hosts: if locked_hosts is True: lock_message = _( "Host attributes locked (You cannot edit this host)") elif isinstance(locked_hosts, str): lock_message = locked_hosts if lock_message: html.div(lock_message, class_="info") html.begin_form("edit_host", method="POST") html.prevent_password_auto_completion() basic_attributes = [ # attribute name, valuepec, default value ("host", self._vs_host_name(), self._host.name()), ] if self._is_cluster(): basic_attributes += [ # attribute name, valuepec, default value ( "nodes", self._vs_cluster_nodes(), self._host.cluster_nodes() if self._host else [], ), ] configure_attributes( new=self._mode != "edit", hosts={self._host.name(): self._host} if self._mode != "new" else {}, for_what="host" if not self._is_cluster() else "cluster", parent=watolib.Folder.current(), basic_attributes=basic_attributes, ) if self._mode != "edit": html.set_focus("host") forms.end() html.hidden_fields() html.end_form()
def page(self): # Let exceptions from loading notification scripts happen now watolib.load_notification_scripts() html.begin_form("user", method="POST") html.prevent_password_auto_completion() forms.header(_("Identity")) # ID forms.section(_("Username"), simple=not self._is_new_user) if self._is_new_user: vs_user_id = UserID(allow_empty=False) else: vs_user_id = FixedValue(self._user_id) vs_user_id.render_input("user_id", self._user_id) def lockable_input(name, dflt): if not self._is_locked(name): html.text_input(name, self._user.get(name, dflt), size=50) else: html.write_text(self._user.get(name, dflt)) html.hidden_field(name, self._user.get(name, dflt)) # Full name forms.section(_("Full name")) lockable_input('alias', self._user_id) html.help(_("Full name or alias of the user")) # Email address forms.section(_("Email address")) email = self._user.get("email", "") if not self._is_locked("email"): EmailAddressUnicode().render_input("email", email) else: html.write_text(email) html.hidden_field("email", email) html.help( _("The email address is optional and is needed " "if the user is a monitoring contact and receives notifications " "via Email.")) forms.section(_("Pager address")) lockable_input('pager', '') html.help(_("The pager address is optional ")) if cmk.is_managed_edition(): forms.section(self._vs_customer.title()) self._vs_customer.render_input("customer", managed.get_customer_id(self._user)) html.help(self._vs_customer.help()) vs_sites = self._vs_sites() forms.section(vs_sites.title()) authorized_sites = self._user.get("authorized_sites", vs_sites.default_value()) if not self._is_locked("authorized_sites"): vs_sites.render_input("authorized_sites", authorized_sites) else: html.write_html(vs_sites.value_to_text(authorized_sites)) html.help(vs_sites.help()) self._show_custom_user_attributes('ident') forms.header(_("Security")) forms.section(_("Authentication")) is_automation = self._user.get("automation_secret", None) is not None html.radiobutton("authmethod", "password", not is_automation, _("Normal user login with password")) html.open_ul() html.open_table() html.open_tr() html.td(_("password:"******"_password_" + self._pw_suffix(), autocomplete="new-password") html.close_td() html.close_tr() html.open_tr() html.td(_("repeat:")) html.open_td() html.password_input("_password2_" + self._pw_suffix(), autocomplete="new-password") html.write_text(" (%s)" % _("optional")) html.close_td() html.close_tr() html.open_tr() html.td("%s:" % _("Enforce change")) html.open_td() # Only make password enforcement selection possible when user is allowed to change the PW if self._is_new_user or config.user_may(self._user_id, 'general.edit_profile') and config.user_may( self._user_id, 'general.change_password'): html.checkbox("enforce_pw_change", self._user.get("enforce_pw_change", False), label=_("Change password at next login or access")) else: html.write_text( _("Not permitted to change the password. Change can not be enforced.")) else: html.i(_('The password can not be changed (It is locked by the user connector).')) html.hidden_field('_password', '') html.hidden_field('_password2', '') html.close_td() html.close_tr() html.close_table() html.close_ul() html.radiobutton("authmethod", "secret", is_automation, _("Automation secret for machine accounts")) html.open_ul() html.text_input("_auth_secret", self._user.get("automation_secret", ""), size=30, id_="automation_secret") html.write_text(" ") html.open_b(style=["position: relative", "top: 4px;"]) html.write(" ") html.icon_button("javascript:cmk.wato.randomize_secret('automation_secret', 20);", _("Create random secret"), "random") html.close_b() html.close_ul() html.help( _("If you want the user to be able to login " "then specify a password here. Users without a login make sense " "if they are monitoring contacts that are just used for " "notifications. The repetition of the password is optional. " "<br>For accounts used by automation processes (such as fetching " "data from views for further procession), set the method to " "<u>secret</u>. The secret will be stored in a local file. Processes " "with read access to that file will be able to use Multisite as " "a webservice without any further configuration.")) # Locking forms.section(_("Disable password"), simple=True) if not self._is_locked('locked'): html.checkbox("locked", self._user.get("locked", False), label=_("disable the login to this account")) else: html.write_text( _('Login disabled') if self._user.get("locked", False) else _('Login possible')) html.hidden_field('locked', '1' if self._user.get("locked", False) else '') html.help( _("Disabling the password will prevent a user from logging in while " "retaining the original password. Notifications are not affected " "by this setting.")) forms.section(_("Idle timeout")) idle_timeout = self._user.get("idle_timeout") if not self._is_locked("idle_timeout"): watolib.get_vs_user_idle_timeout().render_input("idle_timeout", idle_timeout) else: html.write_text(idle_timeout) html.hidden_field("idle_timeout", idle_timeout) # Roles forms.section(_("Roles")) entries = self._roles.items() entries.sort(key=lambda x: (x[1]["alias"], x[0])) is_member_of_at_least_one = False for role_id, role in entries: if not self._is_locked("roles"): html.checkbox("role_" + role_id, role_id in self._user.get("roles", [])) url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)]) html.a(role["alias"], href=url) html.br() else: is_member = role_id in self._user.get("roles", []) if is_member: is_member_of_at_least_one = True url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)]) html.a(role["alias"], href=url) html.br() html.hidden_field("role_" + role_id, '1' if is_member else '') if self._is_locked('roles') and not is_member_of_at_least_one: html.i(_('No roles assigned.')) self._show_custom_user_attributes('security') # Contact groups forms.header(_("Contact Groups"), isopen=False) forms.section() groups_page_url = watolib.folder_preserving_link([("mode", "contact_groups")]) group_assign_url = watolib.folder_preserving_link([("mode", "rulesets"), ("group", "grouping")]) if not self._contact_groups: html.write( _("Please first create some <a href='%s'>contact groups</a>") % groups_page_url) else: entries = sorted([(group['alias'] or c, c) for c, group in self._contact_groups.items() ]) is_member_of_at_least_one = False for alias, gid in entries: is_member = gid in self._user.get("contactgroups", []) if not self._is_locked('contactgroups'): html.checkbox("cg_" + gid, gid in self._user.get("contactgroups", [])) else: if is_member: is_member_of_at_least_one = True html.hidden_field("cg_" + gid, '1' if is_member else '') if not self._is_locked('contactgroups') or is_member: url = watolib.folder_preserving_link([("mode", "edit_contact_group"), ("edit", gid)]) html.a(alias, href=url) html.br() if self._is_locked('contactgroups') and not is_member_of_at_least_one: html.i(_('No contact groups assigned.')) html.help( _("Contact groups are used to assign monitoring " "objects to users. If you haven't defined any contact groups yet, " "then first <a href='%s'>do so</a>. Hosts and services can be " "assigned to contact groups using <a href='%s'>rules</a>.<br><br>" "If you do not put the user into any contact group " "then no monitoring contact will be created for the user.") % (groups_page_url, group_assign_url)) forms.header(_("Notifications"), isopen=False) if not self._rbn_enabled(): forms.section(_("Enabling"), simple=True) html.checkbox("notifications_enabled", self._user.get("notifications_enabled", False), label=_("enable notifications")) html.help( _("Notifications are sent out " "when the status of a host or service changes.")) # Notification period forms.section(_("Notification time period")) choices = [(id_, "%s" % (tp["alias"])) for (id_, tp) in self._timeperiods.items()] html.dropdown("notification_period", choices, deflt=self._user.get("notification_period"), ordered=True) html.help( _("Only during this time period the " "user will get notifications about host or service alerts.")) # Notification options notification_option_names = { # defined here: _() must be executed always! "host": { "d": _("Host goes down"), "u": _("Host gets unreachble"), "r": _("Host goes up again"), }, "service": { "w": _("Service goes into warning state"), "u": _("Service goes into unknown state"), "c": _("Service goes into critical state"), "r": _("Service recovers to OK"), }, "both": { "f": _("Start or end of flapping state"), "s": _("Start or end of a scheduled downtime"), } } forms.section(_("Notification Options")) for title, what, opts in [(_("Host events"), "host", "durfs"), (_("Service events"), "service", "wucrfs")]: html.write_text("%s:" % title) html.open_ul() user_opts = self._user.get(what + "_notification_options", opts) for opt in opts: opt_name = notification_option_names[what].get( opt, notification_option_names["both"].get(opt)) html.checkbox(what + "_" + opt, opt in user_opts, label=opt_name) html.br() html.close_ul() html.help( _("Here you specify which types of alerts " "will be notified to this contact. Note: these settings will only be saved " "and used if the user is member of a contact group.")) forms.section(_("Notification Method")) watolib.get_vs_flexible_notifications().render_input( "notification_method", self._user.get("notification_method")) else: forms.section(_("Fallback notifications"), simple=True) html.checkbox("fallback_contact", self._user.get("fallback_contact", False), label=_("Receive fallback notifications")) html.help( _("In case none of your notification rules handles a certain event a notification " "will be sent to this contact. This makes sure that in that case at least <i>someone</i> " "gets notified. Furthermore this contact will be used for notifications to any host or service " "that is not known to the monitoring. This can happen when you forward notifications " "from the Event Console.<br><br>Notification fallback can also configured in the global " "setting <a href=\"wato.py?mode=edit_configvar&varname=notification_fallback_email\">" "Fallback email address for notifications</a>.")) self._show_custom_user_attributes('notify') forms.header(_("Personal Settings"), isopen=False) select_language(self._user) self._show_custom_user_attributes('personal') # Later we could add custom macros here, which then could be used # for notifications. On the other hand, if we implement some check_mk # --notify, we could directly access the data in the account with the need # to store values in the monitoring core. We'll see what future brings. forms.end() html.button("save", _("Save")) if self._is_new_user: html.set_focus("user_id") else: html.set_focus("alias") html.hidden_fields() html.end_form()