Esempio n. 1
0
    def action(self):
        if not html.check_transaction():
            return "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)]

        # 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"]

        # 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 "users"
Esempio n. 2
0
def edit_annotation():
    site_id = html.request.var("anno_site") or ""
    hostname = html.request.var("anno_host")
    service = html.request.var("anno_service") or None
    fromtime = float(html.request.var("anno_from"))
    untiltime = float(html.request.var("anno_until"))
    site_host_svc = (site_id, hostname, service)

    # Find existing annotation with this specification
    annotations = availability.load_annotations()
    annotation = availability.find_annotation(annotations, site_host_svc,
                                              fromtime, untiltime)

    if not annotation:
        value = {
            "from": fromtime,
            "until": untiltime,
            "text": "",
        }
    else:
        value = annotation.copy()

    value["host"] = hostname
    value["service"] = service
    value["site"] = site_id

    if html.check_transaction():
        try:
            vs = _vs_annotation()
            value = vs.from_html_vars("_editanno")
            vs.validate_value(value, "_editanno")

            site_host_svc = value["site"], value["host"], value["service"]
            del value["site"]
            del value["host"]
            value["date"] = time.time()
            value["author"] = config.user.id
            availability.update_annotations(site_host_svc,
                                            value,
                                            replace_existing=annotation)
            html.request.del_var("filled_in")
            return False
        except MKUserError as e:
            html.user_error(e)

    title = _("Edit annotation of ") + hostname
    if service:
        title += "/" + service

    html.body_start(title)
    html.top_heading(title)

    html.begin_context_buttons()
    html.context_button(_("Abort"), html.makeuri([("anno_host", "")]), "abort")
    html.end_context_buttons()

    html.begin_form("editanno", method="GET")
    _vs_annotation().render_input_as_form("_editanno", value)

    html.button("save", _("Save"))

    html.hidden_fields()
    html.end_form()

    html.bottom_footer()
    html.body_end()
    return True
Esempio n. 3
0
    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"))
Esempio n. 4
0
    def action(self):
        if not html.check_transaction():
            return "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)
            return "tags", _("Created new host tag group '%s'") % changed_tag_group.title

        # 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 = [], {}
        new_by_title = {tag.title: tag.id for tag in changed_tag_group.tags}

        for former_tag in self._untainted_tag_group.tags:
            # Detect renaming
            if former_tag.title in new_by_title:
                new_id = new_by_title[former_tag.title]
                if new_id != former_tag.id:
                    # new_id may be None
                    replace_tag_ids[former_tag.id] = new_id
                    continue

            # Detect removal
            if former_tag.id is not None \
                    and former_tag.id not in [ tmp_tag.id for tmp_tag in changed_tag_group.tags ]:
                # remove explicit tag (hosts/folders) or remove it from tag specs (rules)
                remove_tag_ids.append(former_tag.id)

        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(operation)
        if message:
            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))
            return "tags", message is not True and message or None

        return "tags"
Esempio n. 5
0
    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.check_transaction():
                self._folder.delete_subfolder(
                    html.request.var("_delete_folder"))
            return redirect(mode_url("folder", folder=self._folder.path()))

        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(mode_url("folder", folder=self._folder.path()))

        # 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(mode_url("folder", folder=self._folder.path()))

        # 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."
                  ))

        # 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"):
            self._move_to_imported_folders(selected_host_names)
            return None

        # 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(
                    mode_url(mode_name,
                             folder=watolib.Folder.current().path(),
                             search=search_text,
                             selection=weblib.selection_id()))

        return None
Esempio n. 6
0
    def action(self):
        if html.request.var("_search"):  # just commit to search form
            return

        # 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

        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

        # 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

        # bulk operation on hosts
        if not html.transaction_valid():
            return

        # Host table: No error message on search filter reset
        if html.request.var("_hosts_reset_sorting") or html.request.var("_hosts_sort"):
            return

        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 "bulkinventory"

        if html.request.var("_parentscan"):
            return "parentscan"

        # 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)
            return None, _("Moved %d hosts to %s") % (len(selected_host_names),
                                                      target_folder.title())

        # 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 "bulkedit"

        if html.request.var("_bulk_cleanup"):
            return "bulkcleanup"
Esempio n. 7
0
def _show_page_user_profile(change_pw):
    start_async_replication = False

    if not config.user.id:
        raise MKUserError(None, _('Not logged in.'))

    if not config.user.may('general.edit_profile') and not config.user.may(
            'general.change_password'):
        raise MKAuthException(_("You are not allowed to edit your user profile."))

    if not config.wato_enabled:
        raise MKAuthException(_('User profiles can not be edited (WATO is disabled).'))

    success = None
    if html.request.has_var('_save') and html.check_transaction():
        users = userdb.load_users(lock=True)

        try:
            # Profile edit (user options like language etc.)
            if config.user.may('general.edit_profile'):
                if not change_pw:
                    set_lang = html.get_checkbox('_set_lang')
                    language = html.request.var('language')
                    # Set the users language if requested
                    if set_lang:
                        if language == '':
                            language = None
                        # Set custom language
                        users[config.user.id]['language'] = language
                        config.user.set_attribute("language", language)
                        html.set_language_cookie(language)

                    else:
                        # Remove the customized language
                        if 'language' in users[config.user.id]:
                            del users[config.user.id]['language']
                        config.user.unset_attribute("language")

                    # load the new language
                    cmk.gui.i18n.localize(config.user.language())

                    user = users.get(config.user.id)
                    if config.user.may('general.edit_notifications') and user.get(
                            "notifications_enabled"):
                        value = forms.get_input(watolib.get_vs_flexible_notifications(),
                                                "notification_method")
                        users[config.user.id]["notification_method"] = value

                    # Custom attributes
                    if config.user.may('general.edit_user_attributes'):
                        for name, attr in userdb.get_user_attributes():
                            if attr.user_editable():
                                if not attr.permission() or config.user.may(attr.permission()):
                                    vs = attr.valuespec()
                                    value = vs.from_html_vars('ua_' + name)
                                    vs.validate_value(value, "ua_" + name)
                                    users[config.user.id][name] = value

            # Change the password if requested
            password_changed = False
            if config.user.may('general.change_password'):
                cur_password = html.request.var('cur_password')
                password = html.request.var('password')
                password2 = html.request.var('password2', '')

                if change_pw:
                    # 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 cur_password and password:
                    if userdb.hook_login(config.user.id, cur_password) in [None, 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)
                    users[config.user.id]['password'] = hash_password(password)
                    users[config.user.id]['last_pw_change'] = int(time.time())

                    if change_pw:
                        # Has been changed, remove enforcement flag
                        del users[config.user.id]['enforce_pw_change']

                    # Increase serial to invalidate old cookies
                    if 'serial' not in users[config.user.id]:
                        users[config.user.id]['serial'] = 1
                    else:
                        users[config.user.id]['serial'] += 1

                    password_changed = True

            # Now, if in distributed environment where users can login to remote sites,
            # set the trigger for pushing the new auth information to the slave sites
            # asynchronous
            if config.user.authorized_login_sites():
                start_async_replication = True

            userdb.save_users(users)

            if password_changed:
                # Set the new cookie to prevent logout for the current user
                login.set_auth_cookie(config.user.id)

            success = True
        except MKUserError as e:
            html.add_user_error(e.varname, e)
    else:
        users = userdb.load_users()

    watolib.init_wato_datastructures(with_wato_lock=True)

    # When in distributed setup, display the replication dialog instead of the normal
    # profile edit dialog after changing the password.
    if start_async_replication:
        user_profile_async_replication_page()
        return

    if change_pw:
        title = _("Change Password")
    else:
        title = _("Edit User Profile")

    html.header(title)

    # Rule based notifications: The user currently cannot simply call the according
    # WATO module due to WATO permission issues. So we cannot show this button
    # right now.
    if not change_pw:
        rulebased_notifications = watolib.load_configuration_settings().get(
            "enable_rulebased_notifications")
        if rulebased_notifications and config.user.may('general.edit_notifications'):
            html.begin_context_buttons()
            url = "wato.py?mode=user_notifications_p"
            html.context_button(_("Notifications"), url, "notifications")
            html.end_context_buttons()
    else:
        reason = html.request.var('reason')
        if reason == 'expired':
            html.p(_('Your password is too old, you need to choose a new password.'))
        else:
            html.p(_('You are required to change your password before proceeding.'))

    if success:
        html.reload_sidebar()
        if change_pw:
            html.message(_("Your password has been changed."))
            raise HTTPRedirect(html.request.var('_origtarget', 'index.py'))
        else:
            html.message(_("Successfully updated user profile."))
            # Ensure theme changes are applied without additional user interaction
            html.immediate_browser_redirect(0.5, html.makeuri([]))

    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

    # Returns true if an attribute is locked and should be read only. Is only
    # checked when modifying an existing user
    locked_attributes = userdb.locked_attributes(user.get('connector'))

    def is_locked(attr):
        return attr in locked_attributes

    html.begin_form("profile", method="POST")
    html.prevent_password_auto_completion()
    html.open_div(class_="wato")
    forms.header(_("Personal Settings"))

    if not change_pw:
        forms.section(_("Name"), simple=True)
        html.write_text(user.get("alias", config.user.id))

    if config.user.may('general.change_password') and not is_locked('password'):
        forms.section(_("Current Password"))
        html.password_input('cur_password', autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input('password', autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input('password2', autocomplete="new-password")

    if not change_pw and config.user.may('general.edit_profile'):
        select_language(user)

        # Let the user configure how he wants to be notified
        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'):
            for name, attr in userdb.get_user_attributes():
                if attr.user_editable():
                    vs = attr.valuespec()
                    forms.section(_u(vs.title()))
                    value = user.get(name, vs.default_value())
                    if not attr.permission() or config.user.may(attr.permission()):
                        vs.render_input("ua_" + name, value)
                        html.help(_u(vs.help()))
                    else:
                        html.write(vs.value_to_text(value))

    # Save button
    forms.end()
    html.button("_save", _("Save"))
    html.close_div()
    html.hidden_fields()
    html.end_form()
    html.footer()
Esempio n. 8
0
def edit_dictionaries(
        dictionaries,  # type: List[Tuple[str, Union[Transform, Dictionary]]]
        value,  # type: Dict[str, Any]
        focus=None,  # type: Optional[str]
        hover_help=True,  # type: bool
        validate=None,  # type: Optional[Callable[[Any], None]]
        buttontext=None,  # type: Optional[str]
        title=None,  # type: Optional[str]
        buttons=None,  # type: List[Tuple[str, str, str]]
        method="GET",  # type: str
        preview=False,  # type: bool
        varprefix="",  # type: str
        formname="form",  # type: str
        consume_transid=True  # type: bool
):

    if html.request.get_ascii_input("filled_in") == formname and html.transaction_valid():
        if not preview and consume_transid:
            html.check_transaction()

        messages = []  # type: List[str]
        new_value = {}  # type: Dict[str, Dict[str, Any]]
        for keyname, vs_dict in dictionaries:
            dict_varprefix = varprefix + keyname
            new_value[keyname] = {}
            try:
                edited_value = vs_dict.from_html_vars(dict_varprefix)
                vs_dict.validate_value(edited_value, dict_varprefix)
                new_value[keyname].update(edited_value)
            except MKUserError as e:
                messages.append("%s: %s" % (vs_dict.title() or _("Properties"), e))
                html.add_user_error(e.varname, e)
            except Exception as e:
                messages.append("%s: %s" % (vs_dict.title() or _("Properties"), e))
                html.add_user_error(None, e)

            if validate and not html.has_user_errors():
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append("%s" % e)
                    html.add_user_error(e.varname, e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, vs_dict in dictionaries:
        dict_varprefix = varprefix + keyname
        subvalue = value.get(keyname, {})
        vs_dict.render_input_as_form(dict_varprefix, subvalue)

    end()
    if buttons:
        for name, button_title, _icon in buttons:
            html.button(name, button_title)
    else:
        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()
    html.end_form()
Esempio n. 9
0
def edit_dictionaries(dictionaries,
                      value,
                      focus=None,
                      hover_help=True,
                      validate=None,
                      buttontext=None,
                      title=None,
                      buttons=None,
                      method="GET",
                      preview=False,
                      varprefix="",
                      formname="form",
                      consume_transid=True):

    # Convert list of entries/dictionaries
    sections = []
    for keyname, d in dictionaries:
        if isinstance(d, list):
            sections.append((keyname, title or _("Properties"), d))
        else:
            sections.append((keyname, None, d))  # valuespec Dictionary, title used from dict

    if html.request.var("filled_in") == formname and html.transaction_valid():
        if not preview and consume_transid:
            html.check_transaction()

        messages = []
        new_value = {}
        for keyname, _section_title, entries in sections:
            if isinstance(entries, list):
                new_value[keyname] = value.get(keyname, {}).copy()
                for name, vs in entries:
                    if len(sections) == 1:
                        vp = varprefix
                    else:
                        vp = keyname + "_" + varprefix
                    try:
                        v = vs.from_html_vars(vp + name)
                        vs.validate_value(v, vp + name)
                        new_value[keyname][name] = v
                    except MKUserError as e:
                        messages.append("%s: %s" % (vs.title(), e))
                        html.add_user_error(e.varname, e)

            else:
                new_value[keyname] = {}
                try:
                    edited_value = entries.from_html_vars(keyname)
                    entries.validate_value(edited_value, keyname)
                    new_value[keyname].update(edited_value)
                except MKUserError as e:
                    messages.append("%s: %s" % (entries.title() or _("Properties"), e))
                    html.add_user_error(e.varname, e)
                except Exception as e:
                    messages.append("%s: %s" % (entries.title() or _("Properties"), e))
                    html.add_user_error(None, e)

            if validate and not html.has_user_errors():
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append(e)
                    html.add_user_error(e.varname, e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, title1, entries in sections:
        subvalue = value.get(keyname, {})
        if isinstance(entries, list):
            header(title1)
            first = True
            for name, vs in entries:
                section(vs.title())
                html.help(vs.help())
                if name in subvalue:
                    v = subvalue[name]
                else:
                    v = vs.default_value()
                if len(sections) == 1:
                    vp = varprefix
                else:
                    vp = keyname + "_" + varprefix
                vs.render_input(vp + name, v)
                if (not focus and first) or (name == focus):
                    vs.set_focus(vp + name)
                    first = False
        else:
            entries.render_input_as_form(keyname, subvalue)

    end()
    if buttons:
        for name, button_title, _icon in buttons:
            html.button(name, button_title)
    else:
        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()
    html.end_form()
Esempio n. 10
0
    def action(self):
        if html.request.var("_delete"):
            delid = html.request.get_ascii_input_mandatory("_delete")

            if delid not in self._roles:
                raise MKUserError(None, _("This role does not exist."))

            if html.transaction_valid() and self._roles[delid].get('builtin'):
                raise MKUserError(None,
                                  _("You cannot delete the builtin roles!"))

            users = userdb.load_users()
            for user in users.values():
                if delid in user["roles"]:
                    raise MKUserError(
                        None,
                        _("You cannot delete roles, that are still in use (%s)!"
                          % delid))

            c = wato_confirm(
                _("Confirm deletion of role %s") % delid,
                _("Do you really want to delete the role %s?") % delid)
            if c:
                self._rename_user_role(delid,
                                       None)  # Remove from existing users
                del self._roles[delid]
                self._save_roles()
                watolib.add_change("edit-roles",
                                   _("Deleted role '%s'") % delid,
                                   sites=config.get_login_sites())
            elif c is False:
                return ""

        elif html.request.var("_clone"):
            if html.check_transaction():
                cloneid = html.request.get_ascii_input_mandatory("_clone")

                try:
                    cloned_role = self._roles[cloneid]
                except KeyError:
                    raise MKUserError(None, _("This role does not exist."))

                newid = cloneid
                while newid in self._roles:
                    newid += "x"

                new_role = {}
                new_role.update(cloned_role)

                new_alias = new_role["alias"]
                while not watolib.is_alias_used("roles", newid, new_alias)[0]:
                    new_alias += _(" (copy)")
                new_role["alias"] = new_alias

                if cloned_role.get("builtin"):
                    new_role["builtin"] = False
                    new_role["basedon"] = cloneid

                self._roles[newid] = new_role
                self._save_roles()
                watolib.add_change("edit-roles",
                                   _("Created new role '%s'") % newid,
                                   sites=config.get_login_sites())
Esempio n. 11
0
def edit_dictionaries(
        dictionaries: 'Sequence[Tuple[str, Union[Transform, Dictionary]]]',
        value: Dict[str, Any],
        focus: Optional[str] = None,
        hover_help: bool = True,
        validate: Optional[Callable[[Any], None]] = None,
        title: Optional[str] = None,
        method: str = "GET",
        preview: bool = False,
        varprefix: str = "",
        formname: str = "form",
        consume_transid: bool = True):

    if html.request.get_ascii_input(
            "filled_in") == formname and html.transaction_valid():
        if not preview and consume_transid:
            html.check_transaction()

        messages: List[str] = []
        new_value: Dict[str, Dict[str, Any]] = {}
        for keyname, vs_dict in dictionaries:
            dict_varprefix = varprefix + keyname
            new_value[keyname] = {}
            try:
                edited_value = vs_dict.from_html_vars(dict_varprefix)
                vs_dict.validate_value(edited_value, dict_varprefix)
                new_value[keyname].update(edited_value)
            except MKUserError as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                html.add_user_error(e.varname, e)
            except Exception as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                html.add_user_error(None, e)

            if validate and not html.has_user_errors():
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append("%s" % e)
                    html.add_user_error(e.varname, e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, vs_dict in dictionaries:
        dict_varprefix = varprefix + keyname
        subvalue = value.get(keyname, {})
        vs_dict.render_input_as_form(dict_varprefix, subvalue)

    end()
    # Should be ignored be hidden_fields, but I do not dare to change it there
    html.request.del_var("filled_in")
    html.hidden_fields()
    html.end_form()
Esempio n. 12
0
def page_crashed(what):
    # Do not reveal crash context information to unauthenticated users or not permitted
    # users to prevent disclosure of internal information
    if not config.user.may("general.see_crash_reports"):
        html.header(_("Internal error"))
        html.show_error("<b>%s:</b> %s" % (_("Internal error"), sys.exc_info()[1]))
        html.p(
            _("An internal error occurred while processing your request. "
              "You can report this issue to your Check_MK administrator. "
              "Detailed information can be found in <tt>var/log/web.log</tt>."))
        html.footer()
        return

    if what == "check":
        site = html.request.var("site")
        host = html.request.var("host")
        service = html.request.var("service")

        tardata = get_crash_report_archive_as_string(site, host, service)
    else:
        tardata = create_gui_crash_report(what)

    info = get_crash_info(tardata)

    if what == "check":
        title = _("Crashed Check Reporting")
    else:
        title = _("Internal error")

    html.header(title)

    show_context_buttons(what, tardata)

    if html.request.has_var("_report") and html.check_transaction():
        details = handle_report_form(tardata, what)
    else:
        details = {}

    if what == "gui":
        # Unify different string types from exception messages to a unicode string
        exc_value = sys.exc_info()[1]
        try:
            exc_txt = six.text_type(exc_value)
        except UnicodeDecodeError:
            exc_txt = str(exc_value).decode("utf-8")

        html.show_error("<b>%s:</b> %s" % (_("Internal error"), exc_txt))
        html.p(
            _("An internal error occured while processing your request. "
              "You can report this issue to the Check_MK team to help "
              "fixing this issue. Please use the form below for reporting."))

    if info:
        warn_about_local_files(info)
        show_report_form(what, details)
        show_crash_report(info)
        show_crash_report_details(info)
    else:
        report_url = html.makeuri([("subject", "Check_MK Crash Report - " + get_version(what))],
                                  filename="mailto:" + get_crash_report_target(what))
        html.message(
            _("This crash report is in a legacy format and can not be submitted "
              "automatically. Please download it manually and send it to <a href=\"%s\">%s</a>") %
            (report_url, get_crash_report_target(what)))
        show_old_dump_trace(tardata)

    show_agent_output(tardata)

    html.footer()
Esempio n. 13
0
    def page(self):
        watolib.init_wato_datastructures(with_wato_lock=True)

        if not config.user.may('wato.diag_host'):
            raise MKAuthException(_('You are not permitted to perform this action.'))

        if not html.check_transaction():
            raise MKAuthException(_("Invalid transaction"))

        request = self.webapi_request()

        hostname = request.get("host")
        if not hostname:
            raise MKGeneralException(_('The hostname is missing.'))

        host = watolib.Host.host(hostname)

        if not host:
            raise MKGeneralException(_('The given host does not exist.'))
        if host.is_cluster():
            raise MKGeneralException(_('This view does not support cluster hosts.'))

        host.need_permission("read")

        _test = request.get('_test')
        if not _test:
            raise MKGeneralException(_('The test is missing.'))

        # Execute a specific test
        if _test not in dict(ModeDiagHost.diag_host_tests()).keys():
            raise MKGeneralException(_('Invalid test.'))

        # TODO: Use ModeDiagHost._vs_rules() for processing/validation?
        args = [""] * 13
        for idx, what in enumerate([
                'ipaddress',
                'snmp_community',
                'agent_port',
                'snmp_timeout',
                'snmp_retries',
                'tcp_connect_timeout',
        ]):
            args[idx] = request.get(what, "")

        if config.user.may('wato.add_or_modify_executables'):
            args[6] = request.get("datasource_program", "")

        if request.get("snmpv3_use"):
            snmpv3_use = {
                "0": "noAuthNoPriv",
                "1": "authNoPriv",
                "2": "authPriv",
            }.get(request.get("snmpv3_use"))
            args[7] = snmpv3_use
            if snmpv3_use != "noAuthNoPriv":
                snmpv3_auth_proto = {
                    DropdownChoice.option_id("md5"): "md5",
                    DropdownChoice.option_id("sha"): "sha"
                }.get(request.get("snmpv3_auth_proto"))
                args[8] = snmpv3_auth_proto
                args[9] = request.get("snmpv3_security_name")
                args[10] = request.get("snmpv3_security_password")
                if snmpv3_use == "authPriv":
                    snmpv3_privacy_proto = {
                        DropdownChoice.option_id("DES"): "DES",
                        DropdownChoice.option_id("AES"): "AES"
                    }.get(request.get("snmpv3_privacy_proto"))
                    args[11] = snmpv3_privacy_proto
                    args[12] = request.get("snmpv3_privacy_password")
            else:
                args[9] = request.get("snmpv3_security_name")

        result = watolib.check_mk_automation(host.site_id(), "diag-host", [hostname, _test] + args)
        return {
            "next_transid": html.transaction_manager.fresh_transid(),
            "status_code": result[0],
            "output": result[1],
        }