def action(self) -> ActionResult: delname = request.var("_delete") if not delname: return redirect(mode_url("timeperiods")) if not transactions.check_transaction(): return redirect(mode_url("timeperiods")) if delname in watolib.timeperiods.builtin_timeperiods(): raise MKUserError("_delete", _("Builtin timeperiods can not be modified")) usages = self._find_usages_of_timeperiod(delname) if usages: message = "<b>%s</b><br>%s:<ul>" % \ (_("You cannot delete this timeperiod."), _("It is still in use by")) for title, link in usages: message += '<li><a href="%s">%s</a></li>\n' % (link, title) message += "</ul>" raise MKUserError(None, message) del self._timeperiods[delname] watolib.timeperiods.save_timeperiods(self._timeperiods) watolib.add_change("edit-timeperiods", _("Deleted timeperiod %s") % delname) return redirect(mode_url("timeperiods"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return redirect(mode_url("tags")) vs = self._valuespec() aux_tag_spec = vs.from_html_vars("aux_tag") vs.validate_value(aux_tag_spec, "aux_tag") self._aux_tag = cmk.utils.tags.AuxTag(aux_tag_spec) self._aux_tag.validate() changed_hosttags_config = cmk.utils.tags.TagConfig() changed_hosttags_config.parse_config(self._tag_config_file.load_for_reading()) if self._new: changed_hosttags_config.aux_tag_list.append(self._aux_tag) else: changed_hosttags_config.aux_tag_list.update(self._id, self._aux_tag) try: changed_hosttags_config.validate_config() except MKGeneralException as e: raise MKUserError(None, "%s" % e) self._tag_config_file.save(changed_hosttags_config.get_dict_format()) return redirect(mode_url("tags"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return redirect(mode_url("tags")) vs = self._valuespec() tag_group_spec = vs.from_html_vars("tag_group") vs.validate_value(tag_group_spec, "tag_group") # Create new object with existing host tags changed_hosttags_config = cmk.utils.tags.TagConfig() changed_hosttags_config.parse_config( self._tag_config_file.load_for_modification()) changed_tag_group = cmk.utils.tags.TagGroup(tag_group_spec) self._tag_group = changed_tag_group if self._new: # Inserts and verifies changed tag group changed_hosttags_config.insert_tag_group(changed_tag_group) try: changed_hosttags_config.validate_config() except MKGeneralException as e: raise MKUserError(None, "%s" % e) self._save_tags_and_update_hosts( changed_hosttags_config.get_dict_format()) add_change( "edit-hosttags", _("Created new host tag group '%s'") % changed_tag_group.id) flash( _("Created new host tag group '%s'") % changed_tag_group.title) return redirect(mode_url("tags")) # Updates and verifies changed tag group changed_hosttags_config.update_tag_group(changed_tag_group) try: changed_hosttags_config.validate_config() except MKGeneralException as e: raise MKUserError(None, "%s" % e) remove_tag_ids, replace_tag_ids = identify_modified_tags( changed_tag_group, self._untainted_tag_group) tg_id = self._tag_group.id if tg_id is None: raise Exception("tag group ID not set") operation = OperationReplaceGroupedTags(tg_id, remove_tag_ids, replace_tag_ids) # Now check, if any folders, hosts or rules are affected message = _rename_tags_after_confirmation(self.breadcrumb(), operation) if message is False: return FinalizeRequest(code=200) self._save_tags_and_update_hosts( changed_hosttags_config.get_dict_format()) add_change("edit-hosttags", _("Edited host tag group %s (%s)") % (message, self._id)) if isinstance(message, str): flash(message) return redirect(mode_url("tags"))
def _import(self, csv_reader: CSVReader) -> ActionResult: if self._has_title_line: try: next(csv_reader) # skip header except StopIteration: pass num_succeeded, num_failed = 0, 0 fail_messages = [] selected = [] imported_hosts = [] for row_num, row in enumerate(csv_reader): if not row: continue # skip empty lines host_name, attributes = self._get_host_info_from_row(row, row_num) try: watolib.Folder.current().create_hosts( [(host_name, attributes, None)], bake_hosts=False, ) imported_hosts.append(host_name) selected.append('_c_%s' % host_name) num_succeeded += 1 except Exception as e: fail_messages.append( _("Failed to create a host from line %d: %s") % (csv_reader.line_num, e)) num_failed += 1 watolib.hosts_and_folders.try_bake_agents_for_hosts(imported_hosts) self._delete_csv_file() msg = _("Imported %d hosts into the current folder.") % num_succeeded if num_failed: msg += "<br><br>" + (_("%d errors occured:") % num_failed) msg += "<ul>" for fail_msg in fail_messages: msg += "<li>%s</li>" % fail_msg msg += "</ul>" if num_succeeded > 0 and html.request.var( "do_service_detection") == "1": # Create a new selection for performing the bulk discovery config.user.set_rowselection( weblib.selection_id(), 'wato-folder-/' + watolib.Folder.current().path(), selected, 'set') return redirect( mode_url("bulkinventory", _bulk_inventory='1', show_checkboxes='1')) flash(msg) return redirect(mode_url("folder"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return redirect(mode_url("folder", folder=watolib.Folder.current().path())) count = html.request.get_integer_input_mandatory("count") folders = html.request.get_integer_input_mandatory("folders") levels = html.request.get_integer_input_mandatory("levels") created = self._create_random_hosts(watolib.Folder.current(), count, folders, levels) flash(_("Added %d random hosts.") % created) return redirect(mode_url("folder", folder=watolib.Folder.current().path()))
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"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return None vs = self._valuespec() self._connection_cfg = vs.from_html_vars("connection") vs.validate_value(self._connection_cfg, "connection") self._connection_cfg["type"] = "ldap" if self._new: self._connections.insert(0, self._connection_cfg) self._connection_id = self._connection_cfg["id"] else: self._connection_cfg["id"] = self._connection_id self._connections[self._connection_nr] = self._connection_cfg assert self._connection_id is not None if self._new: log_what = "new-ldap-connection" log_text = _("Created new LDAP connection") else: log_what = "edit-ldap-connection" log_text = _("Changed LDAP connection %s") % self._connection_id self._add_change(log_what, log_text) save_connection_config(self._connections) config.user_connections = self._connections # make directly available on current page if html.request.var("_save"): return redirect(mode_url("ldap_config")) # Handle the case where a user hit "Save & Test" during creation return redirect(self.mode_url(_test="1", id=self._connection_id))
def action(self) -> ActionResult: if not html.check_transaction(): return redirect(mode_url("%s_groups" % self.type_name)) alias = html.request.get_unicode_input_mandatory("alias").strip() self.group = {"alias": alias} self._determine_additional_group_data() if self._new: self._name = html.request.get_ascii_input_mandatory("name").strip() watolib.add_group(self._name, self.type_name, self.group) else: watolib.edit_group(self._name, self.type_name, self.group) return redirect(mode_url("%s_groups" % self.type_name))
def _delete_aux_tag(self) -> ActionResult: del_id = request.get_item_input("_del_aux", dict(self._tag_config.aux_tag_list.get_choices()))[1] # Make sure that this aux tag is not begin used by any tag group for group in self._tag_config.tag_groups: for grouped_tag in group.tags: if del_id in grouped_tag.aux_tag_ids: raise MKUserError( None, _("You cannot delete this auxiliary tag. " "It is being used in the tag group <b>%s</b>.") % group.title) message = _rename_tags_after_confirmation(self.breadcrumb(), OperationRemoveAuxTag(del_id)) if message is False: return FinalizeRequest(code=200) if message: self._tag_config.aux_tag_list.remove(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()) add_change("edit-tags", _("Removed auxiliary tag %s (%s)") % (message, del_id)) if isinstance(message, str): flash(message) return redirect(mode_url("tags"))
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()) add_change("edit-tags", _("Removed tag group %s (%s)") % (message, del_id)) if isinstance(message, str): flash(message) return redirect(mode_url("tags"))
def action(self) -> None: job_details_page = ModeBackgroundJobDetails() action_handler = gui_background_job.ActionHandler(job_details_page.breadcrumb()) action_handler.handle_actions() if action_handler.did_delete_job(): if job_details_page.back_url(): raise redirect(job_details_page.back_url()) raise redirect(mode_url("background_jobs_overview"))
def action(self) -> ActionResult: action_handler = gui_background_job.ActionHandler(self.breadcrumb()) action_handler.handle_actions() if action_handler.did_delete_job(): if self._back_url(): raise redirect(self._back_url()) return redirect(mode_url("background_jobs_overview")) return None
def action(self) -> ActionResult: settings = self._vs().from_html_vars("_read_only") self._vs().validate_value(settings, "_read_only") self._settings = settings self._save() flash(_("Saved read only settings")) return redirect(mode_url("read_only"))
def action(self) -> ActionResult: if html.form_submitted("search"): return None alias = html.request.get_unicode_input("alias") unique, info = watolib.is_alias_used("roles", self._role_id, alias) if not unique: raise MKUserError("alias", info) new_id = html.request.get_ascii_input_mandatory("id") if not new_id: raise MKUserError("id", "You have to provide a ID.") if not re.match("^[-a-z0-9A-Z_]*$", new_id): raise MKUserError( "id", _("Invalid role ID. Only the characters a-z, A-Z, 0-9, _ and - are allowed.")) if new_id != self._role_id: if new_id in self._roles: raise MKUserError("id", _("The ID is already used by another role")) self._role["alias"] = alias # based on if not self._role.get("builtin"): basedon = html.request.get_ascii_input_mandatory("basedon") if basedon not in config.builtin_role_ids: raise MKUserError("basedon", _("Invalid valid for based on. Must be id of builtin rule.")) self._role["basedon"] = basedon # Permissions permissions = self._role["permissions"] for var_name, value in html.request.itervars(prefix="perm_"): try: perm = permission_registry[var_name[5:]] except KeyError: continue if value == "yes": permissions[perm.name] = True elif value == "no": permissions[perm.name] = False elif value == "default": try: del permissions[perm.name] except KeyError: pass # Already at defaults if self._role_id != new_id: self._roles[new_id] = self._role del self._roles[self._role_id] self._rename_user_role(self._role_id, new_id) self._save_roles() watolib.add_change("edit-roles", _("Modified user role '%s'") % new_id, sites=config.get_login_sites()) return redirect(mode_url("roles"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return None vs_ical = self._vs_ical() ical = vs_ical.from_html_vars("ical") vs_ical.validate_value(ical, "ical") filename, _ty, content = ical['file'] try: # TODO(ml): If we could open the file in text mode, we would not # need to `decode()` here. data = self._parse_ical(content.decode("utf-8"), ical['horizon']) except Exception as e: if config.debug: raise raise MKUserError('ical_file', _('Failed to parse file: %s') % e) get_vars = { 'timeperiod_p_alias': data.get('descr', data.get('name', filename)), } for day in defines.weekday_ids(): get_vars['%s_0_from' % day] = '' get_vars['%s_0_until' % day] = '' # Default to whole day if not ical["times"]: ical["times"] = [((0, 0), (24, 0))] get_vars['timeperiod_p_exceptions_count'] = "%d" % len(data['events']) for index, event in enumerate(data['events']): index += 1 get_vars['timeperiod_p_exceptions_%d_0' % index] = event['date'] get_vars['timeperiod_p_exceptions_indexof_%d' % index] = "%d" % index get_vars['timeperiod_p_exceptions_%d_1_count' % index] = "%d" % len(ical["times"]) for n, time_spec in enumerate(ical["times"]): n += 1 start_time = ":".join("%02d" % x for x in time_spec[0]) end_time = ":".join("%02d" % x for x in time_spec[1]) get_vars['timeperiod_p_exceptions_%d_1_%d_from' % (index, n)] = start_time get_vars['timeperiod_p_exceptions_%d_1_%d_until' % (index, n)] = end_time get_vars['timeperiod_p_exceptions_%d_1_indexof_%d' % (index, n)] = "%d" % index return redirect(mode_url("edit_timeperiod", **get_vars))
def action(self) -> ActionResult: if not html.check_transaction(): return redirect(mode_url("%s_groups" % self.type_name)) if html.request.var('_delete'): delname = html.request.get_ascii_input_mandatory("_delete") usages = watolib.find_usages_of_group(delname, self.type_name) if usages: message = "<b>%s</b><br>%s:<ul>" % \ (_("You cannot delete this %s group.") % self.type_name, _("It is still in use by")) for title, link in usages: message += '<li><a href="%s">%s</a></li>\n' % (link, title) message += "</ul>" raise MKUserError(None, message) watolib.delete_group(delname, self.type_name) self._groups = self._load_groups() return redirect(mode_url("%s_groups" % self.type_name))
def action(self) -> ActionResult: if not html.check_transaction(): return None vs = self._valuespec() # returns a Dictionary object vs_spec = vs.from_html_vars("timeperiod") vs.validate_value(vs_spec, "timeperiod") self._timeperiod = self._from_valuespec(vs_spec) if self._new: self._name = vs_spec["name"] watolib.add_change("edit-timeperiods", _("Created new time period %s") % self._name) else: watolib.add_change("edit-timeperiods", _("Modified time period %s") % self._name) assert self._name is not None self._timeperiods[self._name] = self._timeperiod watolib.timeperiods.save_timeperiods(self._timeperiods) return redirect(mode_url("timeperiods"))
def action(self) -> ActionResult: if not transactions.check_transaction(): return None if request.var('_try'): try: self._validate_diag_html_vars() except MKUserError as e: user_errors.add(e) return None if request.var('_save'): # Save the ipaddress and/or community vs_host = self._vs_host() new = vs_host.from_html_vars('vs_host') vs_host.validate_value(new, 'vs_host') # If both snmp types have credentials set - snmpv3 takes precedence return_message = [] if "ipaddress" in new: return_message.append(_("IP address")) if "snmp_v3_credentials" in new: if "snmp_community" in new: return_message.append( _("SNMPv3 credentials (SNMPv2 community was discarded)" )) else: return_message.append(_("SNMPv3 credentials")) new["snmp_community"] = new["snmp_v3_credentials"] elif "snmp_community" in new: return_message.append(_("SNMP credentials")) self._host.update_attributes(new) flash(_("Updated attributes: ") + ", ".join(return_message)) return redirect( mode_url( "edit_host", host=self._hostname, folder=watolib.Folder.current().path(), )) return None
def action(self) -> ActionResult: # TODO: remove subclass specific things specifict things (everything with _type == 'user') if not html.check_transaction(): return None title = html.request.get_unicode_input_mandatory("title").strip() if not title: raise MKUserError("title", _("Please specify a title.")) for this_attr in self._attrs: if title == this_attr['title'] and self._name != this_attr['name']: raise MKUserError( "alias", _("This alias is already used by the attribute %s.") % this_attr['name']) topic = html.request.get_unicode_input_mandatory('topic', '').strip() help_txt = html.request.get_unicode_input_mandatory('help', '').strip() show_in_table = html.get_checkbox('show_in_table') add_custom_macro = html.get_checkbox('add_custom_macro') if self._new: self._name = html.request.get_ascii_input_mandatory("name", '').strip() if not self._name: raise MKUserError( "name", _("Please specify a name for the new attribute.")) if ' ' in self._name: raise MKUserError( "name", _("Sorry, spaces are not allowed in attribute names.")) if not re.match("^[-a-z0-9A-Z_]*$", self._name): raise MKUserError( "name", _("Invalid attribute name. Only the characters a-z, A-Z, 0-9, _ and - are allowed." )) if [a for a in self._attrs if a['name'] == self._name]: raise MKUserError( "name", _("Sorry, there is already an attribute with that name.")) ty = html.request.get_ascii_input_mandatory('type', '').strip() if ty not in [t[0] for t in custom_attr_types()]: raise MKUserError('type', _('The choosen attribute type is invalid.')) self._attr = { 'name': self._name, 'type': ty, } self._attrs.append(self._attr) add_change( "edit-%sattr" % self._type, _("Create new %s attribute %s") % (self._type, self._name)) else: add_change( "edit-%sattr" % self._type, _("Modified %s attribute %s") % (self._type, self._name)) self._attr.update({ 'title': title, 'topic': topic, 'help': help_txt, 'show_in_table': show_in_table, 'add_custom_macro': add_custom_macro, }) self._add_extra_attrs_from_html_vars() save_custom_attrs_to_mk_file(self._all_attrs) self._update_config() return redirect(mode_url(self._type + "_attrs"))
def action(self) -> ActionResult: if not html.check_transaction(): return redirect(mode_url("users")) if self._user_id is None: # same as self._is_new_user self._user_id = UserID(allow_empty=False).from_html_vars("user_id") user_attrs = {} else: self._user_id = html.request.get_unicode_input_mandatory("edit").strip() user_attrs = self._users[UserId(self._user_id)].copy() # Full name user_attrs["alias"] = html.request.get_unicode_input_mandatory("alias").strip() # Locking user_attrs["locked"] = html.get_checkbox("locked") increase_serial = False if (UserId(self._user_id) in self._users and self._users[UserId(self._user_id)]["locked"] != user_attrs["locked"] and user_attrs["locked"]): increase_serial = True # when user is being locked now, increase the auth serial # Authentication: Password or Secret auth_method = html.request.var("authmethod") if auth_method == "secret": secret = html.request.get_str_input_mandatory("_auth_secret", "").strip() user_attrs["automation_secret"] = secret user_attrs["password"] = hash_password(secret) increase_serial = True # password changed, reflect in auth serial else: password = html.request.get_str_input_mandatory("_password_" + self._pw_suffix(), '').strip() password2 = html.request.get_str_input_mandatory("_password2_" + self._pw_suffix(), '').strip() # We compare both passwords only, if the user has supplied # the repeation! We are so nice to our power users... # Note: this validation is done before the main-validiation later on # It doesn't make any sense to put this block into the main validation function if password2 and password != password2: raise MKUserError("_password2", _("The both passwords do not match.")) # Detect switch back from automation to password if "automation_secret" in user_attrs: del user_attrs["automation_secret"] if "password" in user_attrs: del user_attrs["password"] # which was the encrypted automation password! if password: user_attrs["password"] = hash_password(password) user_attrs["last_pw_change"] = int(time.time()) increase_serial = True # password changed, reflect in auth serial # PW change enforcement user_attrs["enforce_pw_change"] = html.get_checkbox("enforce_pw_change") if user_attrs["enforce_pw_change"]: increase_serial = True # invalidate all existing user sessions, enforce relogon # Increase serial (if needed) if increase_serial: user_attrs["serial"] = user_attrs.get("serial", 0) + 1 # Email address user_attrs["email"] = EmailAddress().from_html_vars("email") idle_timeout = watolib.get_vs_user_idle_timeout().from_html_vars("idle_timeout") user_attrs["idle_timeout"] = idle_timeout if idle_timeout is not None: user_attrs["idle_timeout"] = idle_timeout elif idle_timeout is None and "idle_timeout" in user_attrs: del user_attrs["idle_timeout"] # Pager user_attrs["pager"] = html.request.get_str_input_mandatory("pager", '').strip() if cmk_version.is_managed_edition(): customer = self._vs_customer.from_html_vars("customer") self._vs_customer.validate_value(customer, "customer") if customer != managed.default_customer_id(): user_attrs["customer"] = customer elif "customer" in user_attrs: del user_attrs["customer"] vs_sites = self._vs_sites() authorized_sites = vs_sites.from_html_vars("authorized_sites") vs_sites.validate_value(authorized_sites, "authorized_sites") if authorized_sites is not None: user_attrs["authorized_sites"] = authorized_sites elif "authorized_sites" in user_attrs: del user_attrs["authorized_sites"] # ntopng if config.is_ntop_available(): ntop_connection = config.ntop_connection # type: ignore[attr-defined] if ntop_connection.get("use_custom_attribute_as_ntop_username"): user_attrs["ntop_alias"] = html.request.get_unicode_input_mandatory("ntop_alias") # Roles user_attrs["roles"] = [ role for role in self._roles.keys() if html.get_checkbox("role_" + role) ] # Language configuration language = html.request.get_ascii_input_mandatory("language", "") if language != "_default_": user_attrs["language"] = language elif "language" in user_attrs: del user_attrs["language"] # Contact groups cgs = [] for c in self._contact_groups: if html.get_checkbox("cg_" + c): cgs.append(c) user_attrs["contactgroups"] = cgs # Notification settings are only active if we do *not* have # rule based notifications! if not self._rbn_enabled(): # Notifications user_attrs["notifications_enabled"] = html.get_checkbox("notifications_enabled") ntp = html.request.var("notification_period") if ntp not in self._timeperiods: ntp = "24X7" user_attrs["notification_period"] = ntp for what, opts in [("host", "durfs"), ("service", "wucrfs")]: user_attrs[what + "_notification_options"] = "".join( [opt for opt in opts if html.get_checkbox(what + "_" + opt)]) value = watolib.get_vs_flexible_notifications().from_html_vars("notification_method") user_attrs["notification_method"] = value else: user_attrs["fallback_contact"] = html.get_checkbox("fallback_contact") # Custom user attributes for name, attr in userdb.get_user_attributes(): value = attr.valuespec().from_html_vars('ua_' + name) user_attrs[name] = value # Generate user "object" to update user_object = {self._user_id: {"attributes": user_attrs, "is_new_user": self._is_new_user}} # The following call validates and updated the users edit_users(user_object) return redirect(mode_url("users"))