def _move_to_imported_folders(self, host_names_to_move) -> None: # Create groups of hosts with the same target folder target_folder_names: Dict[str, List[HostName]] = {} for host_name in host_names_to_move: host = self._folder.host(host_name) imported_folder_name = host.attribute('imported_folder') if imported_folder_name is None: continue target_folder_names.setdefault(imported_folder_name, []).append(host_name) # Remove target folder information, now that the hosts are # at their target position. host.remove_attribute('imported_folder') # Now handle each target folder for imported_folder, host_names in target_folder_names.items(): # Next problem: The folder path in imported_folder refers # to the Alias of the folders, not to the internal file # name. And we need to create folders not yet existing. target_folder = self._create_target_folder_from_aliaspath( imported_folder) self._folder.move_hosts(host_names, target_folder) flash( _("Successfully moved hosts to their original folder destinations." ))
def test_flash_dont_escape_html(user_id, request_context): now = datetime.now() with login.UserSessionContext(user_id): on_succeeded_login(user_id, now) # Create and activate session flash(HTML("<script>aaa</script>")) assert get_flashed_messages() == [HTML("<script>aaa</script>")]
def handle_acknowledgement(): if not transactions.check_transaction(): return if request.var("_werk_ack"): werk_id = request.get_integer_input_mandatory("_werk_ack") if werk_id not in g_werks: raise MKUserError("werk", _("This werk does not exist.")) werk = g_werks[werk_id] if werk["compatible"] == "incomp_unack": acknowledge_werk(werk) html.show_message( _("Werk %s - %s has been acknowledged.") % (render_werk_id(werk, with_link=True), render_werk_title(werk)) ) load_werks() # reload ack states after modification render_unacknowleged_werks() elif request.var("_ack_all"): num = len(unacknowledged_incompatible_werks()) acknowledge_all_werks() flash(_("%d incompatible Werks have been acknowledged.") % num) load_werks() # reload ack states after modification html.reload_whole_page()
def _action(self) -> None: assert user.id is not None credentials = load_two_factor_credentials(user.id, lock=True) credential_id = request.get_ascii_input_mandatory("_edit") credential = credentials["webauthn_credentials"].get(credential_id) if credential is None: raise MKUserError("_edit", _("The credential does not exist")) vs = self._valuespec(credential) settings = vs.from_html_vars("profile") vs.validate_value(settings, "profile") credential["alias"] = settings["alias"] save_two_factor_credentials(user.id, credentials) flash(_("Successfully changed the credential.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. origtarget = "user_two_factor_overview.py" if user.authorized_login_sites(): raise redirect( makeuri_contextless(request, [("back", origtarget)], filename="user_profile_replicate.py")) raise redirect(origtarget)
def _action(self) -> None: assert user.id is not None users = userdb.load_users(lock=True) user_spec = users[user.id] cur_password = request.get_str_input_mandatory("cur_password") password = request.get_str_input_mandatory("password") password2 = request.get_str_input_mandatory("password2", "") # Force change pw mode if not cur_password: raise MKUserError("cur_password", _("You need to provide your current password.")) if not password: raise MKUserError("password", _("You need to change your password.")) if cur_password == password: raise MKUserError("password", _("The new password must differ from your current one.")) if userdb.check_credentials(user.id, cur_password) is False: raise MKUserError("cur_password", _("Your old password is wrong.")) if password2 and password != password2: raise MKUserError("password2", _("The both new passwords do not match.")) watolib.verify_password_policy(password) user_spec["password"] = hash_password(password) user_spec["last_pw_change"] = int(time.time()) # In case the user was enforced to change it's password, remove the flag try: del user_spec["enforce_pw_change"] except KeyError: pass # Increase serial to invalidate old authentication cookies if "serial" not in user_spec: user_spec["serial"] = 1 else: user_spec["serial"] += 1 userdb.save_users(users) flash(_("Successfully changed password.")) # Set the new cookie to prevent logout for the current user login.update_auth_cookie(user.id) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. origtarget = request.get_str_input_mandatory("_origtarget", "user_change_pw.py") if user.authorized_login_sites(): raise redirect( makeuri_contextless( request, [("back", origtarget)], filename="user_profile_replicate.py" ) ) raise redirect(origtarget)
def page(self) -> CBORPageResult: assert user.id is not None user.need_permission("general.manage_2fa") raw_data = request.get_data() logger.debug("Raw request: %r", raw_data) data: dict[str, object] = cbor.decode(raw_data) client_data = ClientData(data["clientDataJSON"]) att_obj = AttestationObject(data["attestationObject"]) logger.debug("Client data: %r", client_data) logger.debug("Attestation object: %r", att_obj) auth_data = make_fido2_server().register_complete( session.session_info.webauthn_action_state, client_data, att_obj ) ident = auth_data.credential_data.credential_id.hex() credentials = load_two_factor_credentials(user.id, lock=True) if ident in credentials["webauthn_credentials"]: raise MKGeneralException(_("Your WebAuthn credetial is already in use")) credentials["webauthn_credentials"][ident] = WebAuthnCredential( { "credential_id": ident, "registered_at": int(time.time()), "alias": "", "credential_data": bytes(auth_data.credential_data), } ) save_two_factor_credentials(user.id, credentials) flash(_("Registration successful")) return {"status": "OK"}
def action(self) -> ActionResult: if not html.transaction_valid(): return None action_var = html.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 html.check_transaction(): return redirect(mode_url(self._mode_type.list_mode_name())) entries = self._store.load_for_modification() ident = html.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("delete", entry, _("Removed the %s '%s'") % (self._mode_type.name_singular(), ident)) 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 _action(self) -> None: assert user.id is not None users = userdb.load_users(lock=True) user_spec = users[user.id] language = request.get_ascii_input_mandatory("language", "") # Set the users language if requested to set it explicitly if language != "_default_": user_spec["language"] = language user.language = language set_language_cookie(request, response, language) else: if "language" in user_spec: del user_spec["language"] user.reset_language() # load the new language localize(user.language) if user.may("general.edit_notifications") and user_spec.get( "notifications_enabled"): value = forms.get_input(get_vs_flexible_notifications(), "notification_method") user_spec["notification_method"] = value # Custom attributes if user.may("general.edit_user_attributes"): for name, attr in userdb.get_user_attributes(): if not attr.user_editable(): continue perm_name = attr.permission() if perm_name and not user.may(perm_name): continue vs = attr.valuespec() value = vs.from_html_vars("ua_" + name) vs.validate_value(value, "ua_" + name) # TODO: Dynamically fiddling around with a TypedDict is a bit questionable user_spec[name] = value # type: ignore[literal-required] userdb.save_users(users) flash(_("Successfully updated user profile.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. if user.authorized_login_sites(): back_url = "user_profile_replicate.py?back=user_profile.py" else: back_url = "user_profile.py" # Ensure theme changes are applied without additional user interaction html.reload_whole_page(back_url) html.footer() raise FinalizeRequest(code=200)
def action(self) -> ActionResult: varname = request.var("_varname") if not varname: return None action = request.var("_action") config_variable = config_variable_registry[varname]() def_value = self._default_values[varname] if not transactions.check_transaction(): return None if varname in self._current_settings: self._current_settings[ varname] = not self._current_settings[varname] else: self._current_settings[varname] = not def_value msg = _("Changed Configuration variable %s to %s.") % ( varname, "on" if self._current_settings[varname] else "off", ) save_global_settings(self._current_settings) _changes.add_change( "edit-configvar", msg, domains=[config_variable.domain()], need_restart=config_variable.need_restart(), ) if action == "_reset": flash(msg) return redirect(mode_url("globalvars"))
def _move_to_imported_folders(self, host_names_to_move) -> ActionResult: c = wato_confirm( _("Confirm moving hosts"), _('You are going to move the selected hosts to folders ' 'representing their original folder location in the system ' 'you did the import from. Please make sure that you have ' 'done an <b>inventory</b> before moving the hosts.')) if c is False: # not yet confirmed return FinalizeRequest(code=200) if not c: return None # browser reload # Create groups of hosts with the same target folder target_folder_names: Dict[str, List[HostName]] = {} for host_name in host_names_to_move: host = self._folder.host(host_name) imported_folder_name = host.attribute('imported_folder') if imported_folder_name is None: continue target_folder_names.setdefault(imported_folder_name, []).append(host_name) # Remove target folder information, now that the hosts are # at their target position. host.remove_attribute('imported_folder') # Now handle each target folder for imported_folder, host_names in target_folder_names.items(): # Next problem: The folder path in imported_folder refers # to the Alias of the folders, not to the internal file # name. And we need to create folders not yet existing. target_folder = self._create_target_folder_from_aliaspath(imported_folder) self._folder.move_hosts(host_names, target_folder) flash(_("Successfully moved hosts to their original folder destinations.")) return None
def test_flash(user_id): # Execute the first request flash some message with application_and_request_context(), login.UserSessionContext(user_id): session_id = on_succeeded_login(user_id) # Create and activate session assert session is not None flash("abc") assert session.session_info.flashes == ["abc"] # Now create the second request to get the previously flashed message with application_and_request_context(), login.UserSessionContext(user_id): on_access(user_id, session_id) assert session is not None assert session.session_info.flashes == ["abc"] # Get the flashed messages removes the messages from the session # and subsequent calls to get_flashed_messages return the messages # over and over. assert get_flashed_messages() == [HTML("abc")] assert get_flashed_messages() == [HTML("abc")] assert session.session_info.flashes == [] # Now create the third request that should not have access to the flashed messages since the # second one consumed them. with application_and_request_context(), login.UserSessionContext(user_id): on_access(user_id, session_id) assert session is not None assert session.session_info.flashes == [] assert get_flashed_messages() == []
def action(self) -> ActionResult: folder = watolib.Folder.current() if not html.check_transaction(): return redirect(mode_url("folder", folder=folder.path())) if html.request.var("_update_dns_cache") and self._should_use_dns_cache(): config.user.need_permission("wato.update_dns_cache") num_updated, failed_hosts = watolib.check_mk_automation(self._host.site_id(), "update-dns-cache", []) infotext = _("Successfully updated IP addresses of %d hosts.") % num_updated if failed_hosts: infotext += "<br><br><b>Hostnames failed to lookup:</b> " \ + ", ".join(["<tt>%s</tt>" % h for h in failed_hosts]) flash(infotext) return None if html.request.var("delete"): # Delete this host folder.delete_hosts([self._host.name()]) return redirect(mode_url("folder", folder=folder.path())) attributes = watolib.collect_attributes("host" if not self._is_cluster() else "cluster", new=False) watolib.Host.host(self._host.name()).edit(attributes, self._get_cluster_nodes()) self._host = folder.host(self._host.name()) if html.request.var("services"): return redirect(mode_url("inventory", folder=folder.path(), host=self._host.name())) if html.request.var("diag_host"): return redirect( mode_url("diag_host", folder=folder.path(), host=self._host.name(), _start_on_load="1")) return redirect(mode_url("folder", folder=folder.path()))
def _action(self) -> None: assert config.user.id is not None users = userdb.load_users(lock=True) user = users[config.user.id] language = html.request.get_ascii_input_mandatory('language', "") # Set the users language if requested to set it explicitly if language != "_default_": user['language'] = language config.user.language = language html.set_language_cookie(language) else: if 'language' in user: del user['language'] config.user.reset_language() # load the new language cmk.gui.i18n.localize(config.user.language) if config.user.may('general.edit_notifications') and user.get( "notifications_enabled"): value = forms.get_input(watolib.get_vs_flexible_notifications(), "notification_method") user["notification_method"] = value # Custom attributes if config.user.may('general.edit_user_attributes'): for name, attr in userdb.get_user_attributes(): if not attr.user_editable(): continue if attr.permission() and not config.user.may( attr.permission()): continue vs = attr.valuespec() value = vs.from_html_vars('ua_' + name) vs.validate_value(value, "ua_" + name) user[name] = value userdb.save_users(users) flash(_("Successfully updated user profile.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. if config.user.authorized_login_sites(): back_url = "user_profile_replicate.py?back=user_profile.py" else: back_url = "user_profile.py" # Ensure theme changes are applied without additional user interaction html.reload_whole_page(back_url) html.footer() raise FinalizeRequest(code=200)
def test_flash_escape_html_in_str(user_id, module_wide_request_context): with login.UserContext(user_id): on_succeeded_login(user_id) # Create and activate session flash("<script>aaa</script>") assert get_flashed_messages() == [ HTML("<script>aaa</script>") ]
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 _delete_hosts_after_confirm(self, host_names) -> ActionResult: c = wato_confirm( _("Confirm deletion of %d hosts") % len(host_names), _("Do you really want to delete the %d selected hosts?") % len(host_names)) if c: self._folder.delete_hosts(host_names) flash(_("Successfully deleted %d hosts") % len(host_names)) return redirect(mode_url("folder", folder=self._folder.path())) if c is False: # not yet confirmed return FinalizeRequest(code=200) return None # browser reload
def _show_form(self, profile_changed: bool) -> None: assert config.user.id is not None users = userdb.load_users() if profile_changed: flash(_("Successfully updated user profile.")) # Ensure theme changes are applied without additional user interaction html.reload_whole_page() if html.has_user_errors(): html.show_user_errors() user = users.get(config.user.id) if user is None: html.show_warning(_("Sorry, your user account does not exist.")) html.footer() return html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(_("Personal settings")) forms.section(_("Name"), simple=True) html.write_text(user.get("alias", config.user.id)) select_language(user) # Let the user configure how he wants to be notified rulebased_notifications = rulebased_notifications_enabled() if (not rulebased_notifications and config.user.may('general.edit_notifications') and user.get("notifications_enabled")): forms.section(_("Notifications")) html.help( _("Here you can configure how you want to be notified about host and service problems and " "other monitoring events.")) watolib.get_vs_flexible_notifications().render_input( "notification_method", user.get("notification_method")) if config.user.may('general.edit_user_attributes'): custom_user_attr_topics = get_user_attributes_by_topic() _show_custom_user_attr(user, custom_user_attr_topics.get("personal", [])) forms.header(_("User interface settings")) _show_custom_user_attr( user, custom_user_attr_topics.get("interface", [])) forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def action(self) -> ActionResult: if not transactions.transaction_valid(): return redirect(mode_url("folder")) attributes = watolib.collect_attributes(self._host_type_name(), new=True) cluster_nodes = self._get_cluster_nodes() hostname = request.get_ascii_input_mandatory("host") Hostname().validate_value(hostname, "host") folder = watolib.Folder.current() if transactions.check_transaction(): folder.create_hosts([(hostname, attributes, cluster_nodes)]) self._host = folder.load_host(hostname) inventory_url = watolib.folder_preserving_link( [ ("mode", "inventory"), ("host", self._host.name()), ("_scan", "1"), ] ) create_msg = ( None if self._host.is_ping_host() else ( _( "Successfully created the host. Now you should do a " '<a href="%s">service discovery</a> in order to auto-configure ' "all services to be checked on this host." ) % inventory_url ) ) if request.var("_save"): return redirect(inventory_url) if create_msg: flash(create_msg) if request.var("diag_host"): return redirect( mode_url("diag_host", folder=folder.path(), host=self._host.name(), _try="1") ) return redirect(mode_url("folder", folder=folder.path()))
def action(self) -> ActionResult: folder = Folder.current() if not transactions.check_transaction(): return redirect(mode_url("folder", folder=folder.path())) if request.var("_update_dns_cache") and self._should_use_dns_cache(): user.need_permission("wato.update_dns_cache") update_dns_cache_result = update_dns_cache(self._host.site_id()) infotext = (_("Successfully updated IP addresses of %d hosts.") % update_dns_cache_result.n_updated) if update_dns_cache_result.failed_hosts: infotext += "<br><br><b>Hostnames failed to lookup:</b> " + ", ".join( [ "<tt>%s</tt>" % h for h in update_dns_cache_result.failed_hosts ]) flash(infotext) return None if request.var("delete"): # Delete this host folder.delete_hosts([self._host.name()], automation=delete_hosts) return redirect(mode_url("folder", folder=folder.path())) if request.var("_remove_tls_registration"): remove_tls_registration( {self._host.site_id(): [self._host.name()]}) return None attributes = collect_attributes( "host" if not self._is_cluster() else "cluster", new=False) host = Host.host(self._host.name()) if host is None: flash(f"Host {self._host.name()} could not be found.") return None host.edit(attributes, self._get_cluster_nodes()) self._host = folder.load_host(self._host.name()) if request.var("_save"): return redirect( mode_url("inventory", folder=folder.path(), host=self._host.name())) if request.var("diag_host"): return redirect( mode_url("diag_host", folder=folder.path(), host=self._host.name(), _start_on_load="1")) return redirect(mode_url("folder", folder=folder.path()))
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"): display_codes, credentials[ "backup_codes"] = make_two_factor_backup_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>{c}</tt></li>" for c in display_codes))
def action(self) -> ActionResult: if not transactions.check_transaction(): return None user.need_permission("wato.edit_hosts") changed_attributes = collect_attributes("bulk", new=False) host_names = get_hostnames_from_checkboxes() for host_name in host_names: host = Folder.current().load_host(host_name) host.update_attributes(changed_attributes) # call_hook_hosts_changed() is called too often. # Either offer API in class Host for bulk change or # delay saving until end somehow flash(_("Edited %d hosts") % len(host_names)) return redirect(Folder.current().url())
def page(self) -> CBORPageResult: assert user.id is not None user.need_permission("general.manage_2fa") raw_data = request.get_data() logger.debug("Raw request: %r", raw_data) data: dict[str, object] = cbor.decode(raw_data) client_data = ClientData(data["clientDataJSON"]) att_obj = AttestationObject(data["attestationObject"]) logger.debug("Client data: %r", client_data) logger.debug("Attestation object: %r", att_obj) try: auth_data = make_fido2_server().register_complete( session.session_info.webauthn_action_state, client_data, att_obj) except ValueError as e: if "Invalid origin in ClientData" in str(e): raise MKGeneralException( "The origin %r is not valid. You need to access the UI via HTTPS " "and you need to use a valid host or domain name. See werk #13325 for " "further information" % client_data.get("origin")) from e raise ident = auth_data.credential_data.credential_id.hex() credentials = load_two_factor_credentials(user.id, lock=True) if ident in credentials["webauthn_credentials"]: raise MKGeneralException( _("Your WebAuthn credential is already in use")) credentials["webauthn_credentials"][ident] = WebAuthnCredential({ "credential_id": ident, "registered_at": int(time.time()), "alias": "", "credential_data": bytes(auth_data.credential_data), }) save_two_factor_credentials(user.id, credentials) flash(_("Registration successful")) return {"status": "OK"}
def action(self) -> ActionResult: varname = html.request.var("_varname") if not varname: return None action = html.request.var("_action") config_variable = config_variable_registry[varname]() def_value = self._default_values[varname] if action == "reset" and not is_a_checkbox(config_variable.valuespec()): c = wato_confirm( _("Resetting configuration variable"), _("Do you really want to reset the configuration variable <b>%s</b> " "back to the default value of <b><tt>%s</tt></b>?") % (varname, config_variable.valuespec().value_to_text(def_value))) else: if not html.check_transaction(): return None c = True # no confirmation for direct toggle if c: if varname in self._current_settings: self._current_settings[varname] = not self._current_settings[varname] else: self._current_settings[varname] = not def_value msg = _("Changed Configuration variable %s to %s.") % ( varname, "on" if self._current_settings[varname] else "off") watolib.save_global_settings(self._current_settings) watolib.add_change("edit-configvar", msg, domains=[config_variable.domain()], need_restart=config_variable.need_restart()) if action == "_reset": flash(msg) return redirect(mode_url("globalvars")) if c is False: return FinalizeRequest(code=200) return None
def test_flash(user_id): environ = create_environ() # Execute the first request flash some message with AppContext(DummyApplication(environ, None)), \ RequestContext(htmllib.html(http.Request(environ))) as request, \ login.UserContext(user_id): session_id = on_succeeded_login(user_id) # Create and activate session assert request.session is not None flash("abc") assert session.session_info.flashes == ["abc"] # Now create the second request to get the previously flashed message with AppContext(DummyApplication(environ, None)), \ RequestContext(htmllib.html(http.Request(environ))), \ login.UserContext(user_id): on_access(user_id, session_id) assert request.session is not None assert session.session_info.flashes == ["abc"] # Get the flashed messages removes the messages from the session # and subsequent calls to get_flashed_messages return the messages # over and over. assert get_flashed_messages() == [HTML("abc")] assert get_flashed_messages() == [HTML("abc")] assert session.session_info.flashes == [] # Now create the third request that should not have access to the flashed messages since the # second one consumed them. with AppContext(DummyApplication(environ, None)), \ RequestContext(htmllib.html(http.Request(environ))), \ login.UserContext(user_id): on_access(user_id, session_id) assert request.session is not None assert session.session_info.flashes == [] assert get_flashed_messages() == []
def test_flash_dont_escape_html(user_id, module_wide_request_context): with login.UserSessionContext(user_id): on_succeeded_login(user_id) # Create and activate session flash(HTML("<script>aaa</script>")) assert get_flashed_messages() == [HTML("<script>aaa</script>")]
def _delete_hosts(self, host_names) -> ActionResult: self._folder.delete_hosts(host_names) flash(_("Successfully deleted %d hosts") % len(host_names)) return redirect(self._folder.url())
def action(self) -> ActionResult: if html.request.var("_search"): # just commit to search form return None folder_url = self._folder.url() # Operations on SUBFOLDERS if html.request.var("_delete_folder"): if html.check_transaction(): self._folder.delete_subfolder(html.request.var("_delete_folder")) return redirect(folder_url) if html.request.has_var("_move_folder_to"): if html.check_transaction(): what_folder = watolib.Folder.folder(html.request.var("_ident")) target_folder = watolib.Folder.folder(html.request.var("_move_folder_to")) watolib.Folder.current().move_subfolder_to(what_folder, target_folder) return redirect(folder_url) # Operations on HOSTS # Deletion of single hosts delname = html.request.var("_delete_host") if delname and watolib.Folder.current().has_host(delname): watolib.Folder.current().delete_hosts([delname]) return redirect(folder_url) # Move single hosts to other folders if html.request.has_var("_move_host_to"): hostname = html.request.var("_ident") if hostname and watolib.Folder.current().has_host(hostname): target_folder = watolib.Folder.folder(html.request.var("_move_host_to")) watolib.Folder.current().move_hosts([hostname], target_folder) return redirect(folder_url) # bulk operation on hosts if not html.transaction_valid(): return redirect(folder_url) # Host table: No error message on search filter reset if html.request.var("_hosts_reset_sorting") or html.request.var("_hosts_sort"): return None selected_host_names = get_hostnames_from_checkboxes() if not selected_host_names: raise MKUserError(None, _("Please select some hosts before doing bulk operations on hosts.")) # Move if html.request.var("_bulk_move"): target_folder_path = html.request.var("_bulk_moveto", html.request.var("_top_bulk_moveto")) if target_folder_path == "@": raise MKUserError("_bulk_moveto", _("Please select the destination folder")) target_folder = watolib.Folder.folder(target_folder_path) watolib.Folder.current().move_hosts(selected_host_names, target_folder) flash(_("Moved %d hosts to %s") % (len(selected_host_names), target_folder.title())) return redirect(folder_url) # Move to target folder (from import) if html.request.var("_bulk_movetotarget"): self._move_to_imported_folders(selected_host_names) return redirect(folder_url) # Deletion if html.request.var("_bulk_delete"): return self._delete_hosts(selected_host_names) search_text = html.request.get_unicode_input_mandatory("search", "") for request_var, mode_name in [ ("_bulk_inventory", "bulkinventory"), ("_parentscan", "parentscan"), ("_bulk_edit", "bulkedit"), ("_bulk_cleanup", "bulkcleanup"), ]: if html.request.var(request_var): return redirect( self._folder.url(add_vars=[ ("mode", mode_name), ("search", search_text), ("selection", weblib.selection_id()), ])) return None
def action(self) -> ActionResult: if html.request.var("_search"): # just commit to search form return None # Operations on SUBFOLDERS if html.request.var("_delete_folder"): if html.transaction_valid(): return self._delete_subfolder_after_confirm(html.request.var("_delete_folder")) return None if html.request.has_var("_move_folder_to"): if html.check_transaction(): what_folder = watolib.Folder.folder(html.request.var("_ident")) target_folder = watolib.Folder.folder(html.request.var("_move_folder_to")) watolib.Folder.current().move_subfolder_to(what_folder, target_folder) return None # Operations on HOSTS # Deletion of single hosts delname = html.request.var("_delete_host") if delname and watolib.Folder.current().has_host(delname): return delete_host_after_confirm(delname) # Move single hosts to other folders if html.request.has_var("_move_host_to"): hostname = html.request.var("_ident") if hostname: target_folder = watolib.Folder.folder(html.request.var("_move_host_to")) watolib.Folder.current().move_hosts([hostname], target_folder) return None # bulk operation on hosts if not html.transaction_valid(): return None # Host table: No error message on search filter reset if html.request.var("_hosts_reset_sorting") or html.request.var("_hosts_sort"): return None selected_host_names = get_hostnames_from_checkboxes() if not selected_host_names: raise MKUserError(None, _("Please select some hosts before doing bulk operations on hosts.")) if html.request.var("_bulk_inventory"): return redirect(mode_url("bulkinventory", folder=watolib.Folder.current().path())) if html.request.var("_parentscan"): return redirect(mode_url("parentscan", folder=watolib.Folder.current().path())) # Deletion if html.request.var("_bulk_delete"): return self._delete_hosts_after_confirm(selected_host_names) # Move if html.request.var("_bulk_move"): target_folder_path = html.request.var("_bulk_moveto", html.request.var("_top_bulk_moveto")) if target_folder_path == "@": raise MKUserError("_bulk_moveto", _("Please select the destination folder")) target_folder = watolib.Folder.folder(target_folder_path) watolib.Folder.current().move_hosts(selected_host_names, target_folder) flash(_("Moved %d hosts to %s") % (len(selected_host_names), target_folder.title())) return None # Move to target folder (from import) if html.request.var("_bulk_movetotarget"): return self._move_to_imported_folders(selected_host_names) if html.request.var("_bulk_edit"): return redirect(mode_url("bulkedit", folder=watolib.Folder.current().path())) if html.request.var("_bulk_cleanup"): return redirect(mode_url("bulkcleanup", folder=watolib.Folder.current().path())) return None