def _create_auth_file(callee, users=None): if users is None: users = userdb.load_users() contactgroups = load_contact_group_information() groups = {} for gid, group in contactgroups.items(): if "nagvis_maps" in group and group["nagvis_maps"]: groups[gid] = group["nagvis_maps"] _create_php_file(callee, users, get_role_permissions(), groups)
def list_users(params): """Show all users""" user.need_permission("wato.users") users = [] for user_id, attrs in userdb.load_users(False).items(): user_attributes = _internal_to_api_format(attrs) users.append( serialize_user(user_id, complement_customer(user_attributes))) return constructors.serve_json( constructors.collection_object(domain_type="user_config", value=users))
def execute(self, request): user_profiles = request.user_profiles if not user_profiles: raise MKGeneralException(_('Invalid call: No profiles set.')) users = userdb.load_users(lock=True) for user_id, profile in user_profiles.items(): users[user_id] = profile userdb.save_users(users) return True
def _find_usages_of_contact_group_in_users(name): """Is the contactgroup assigned to a user?""" used_in = [] users = userdb.load_users() entries = users.items() for userid, user in sorted(entries, key=lambda x: x[1].get("alias", x[0])): cgs = user.get("contactgroups", []) if name in cgs: used_in.append(('%s: %s' % (_('User'), user.get('alias', userid)), folder_preserving_link([('mode', 'edit_user'), ('edit', userid)]))) return used_in
def execute(self, api_request): user_profiles = api_request.user_profiles if not user_profiles: raise MKGeneralException(_("Invalid call: No profiles set.")) users = userdb.load_users(lock=True) for user_id, profile in user_profiles.items(): users[user_id] = profile userdb.save_users(users, datetime.now()) return True
def execute(self) -> Iterator[ACResult]: users = userdb.load_users() num_users = len(users) user_warn_threshold = 500 if num_users <= user_warn_threshold: yield ACResultOK(_("You have %d users configured") % num_users) else: yield ACResultWARN( _("You have %d users configured. Please review the number of " "users you have configured in Check_MK.") % num_users)
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 _edit_users(self, request): # A dictionary with the userid as key # Each value is a {"set_attributes": {"alias": "test"}, # "unset_attributes": ["pager", "email"]} user_settings = request.get("users") all_users = userdb.load_users() locked_attributes_by_connection = {} edit_user_objects = {} for user_id, settings in user_settings.items(): if user_id not in all_users: raise MKUserError(None, _("Unknown user: %s") % user_id) user = all_users[user_id] connector_id = user.get("connector") set_attributes = settings.get("set_attributes", {}) unset_attributes = settings.get("unset_attributes", []) if connector_id not in locked_attributes_by_connection: locked_attributes_by_connection[connector_id] = userdb.locked_attributes( connector_id ) locked_attributes = locked_attributes_by_connection[connector_id] for attr in list(set_attributes.keys()) + unset_attributes: if attr in locked_attributes: raise MKUserError( None, _( 'Attribute "%s" of user "%s" can not be changed, ' "because it is locked by the user connection." ) % (attr, user_id), ) user_attrs = copy.deepcopy(user) user_attrs.update(set_attributes) for entry in unset_attributes: if entry not in user_attrs: continue # TODO: Dynamically fiddling around with a TypedDict is a bit questionable del user_attrs[entry] # type: ignore[misc] new_password = set_attributes.get("password") if new_password: user_attrs["password"] = hash_password(new_password) user_attrs["serial"] = user_attrs.get("serial", 0) + 1 edit_user_objects[user_id] = {"attributes": user_attrs, "is_new_user": False} cmk.gui.watolib.users.edit_users(edit_user_objects)
def _set_user_scheme_serial(self): """Set attribute to detect with what cmk version the user was created. We start that with 2.0""" users = load_users(lock=True) for user_id in users: # pre 2.0 user if users[user_id].get("user_scheme_serial") is None: _set_show_mode(users, user_id) # here you could set attributes based on the current scheme users[user_id]["user_scheme_serial"] = USER_SCHEME_SERIAL save_users(users)
def _action(self) -> bool: assert config.user.id is not None users = userdb.load_users(lock=True) user = users[config.user.id] cur_password = html.request.get_str_input_mandatory('cur_password') password = html.request.get_str_input_mandatory('password') password2 = html.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(config.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['password'] = hash_password(password) user['last_pw_change'] = int(time.time()) # In case the user was enforced to change it's password, remove the flag try: del user['enforce_pw_change'] except KeyError: pass # Increase serial to invalidate old authentication cookies if 'serial' not in user: user['serial'] = 1 else: user['serial'] += 1 userdb.save_users(users) # Set the new cookie to prevent logout for the current user login.update_auth_cookie(config.user.id) return True
def _bulk_delete_users_after_confirm(self): selected_users = [] users = userdb.load_users() for varname, _value in html.request.itervars(prefix="_c_user_"): if html.get_checkbox(varname): user = base64.b64decode( varname.split("_c_user_")[-1].encode("utf-8")).decode("utf-8") if user in users: selected_users.append(user) if selected_users: delete_users(selected_users)
def _synchronize_profile(self, site_id, site, user_id): users = userdb.load_users(lock=False) if user_id not in users: raise MKUserError(None, _('The requested user does not exist')) start = time.time() result = push_user_profiles_to_site_transitional_wrapper(site, {user_id: users[user_id]}) duration = time.time() - start watolib.ActivateChanges().update_activation_time(site_id, ACTIVATION_TIME_PROFILE_SYNC, duration) return result
def _show_form(self, profile_changed: bool) -> None: assert config.user.id is not None users = userdb.load_users() change_reason = html.request.get_ascii_input('reason') if change_reason == 'expired': html.p(_('Your password is too old, you need to choose a new password.')) elif change_reason == 'enforced': html.p(_('You are required to change your password before proceeding.')) if profile_changed: html.show_message(_("Your password has been changed.")) if change_reason: raise HTTPRedirect(html.request.get_str_input_mandatory('_origtarget', 'index.py')) 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 locked_attributes = userdb.locked_attributes(user.get('connector')) if "password" in locked_attributes: raise MKUserError( "cur_password", _("You can not change your password, because it is " "managed by another system.")) html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(self._page_title()) forms.section(_("Current Password")) html.password_input('cur_password', autocomplete="new-password") forms.section(_("New Password")) html.password_input('password', autocomplete="new-password") forms.section(_("New Password Confirmation")) html.password_input('password2', autocomplete="new-password") forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def page(self): with table_element("roles") as table: users = userdb.load_users() for rid, role in sorted(self._roles.items(), key=lambda a: (a[1]["alias"], a[0])): table.row() # Actions table.cell(_("Actions"), css=["buttons"]) edit_url = folder_preserving_link([("mode", "edit_role"), ("edit", rid)]) clone_url = make_action_link([("mode", "roles"), ("_clone", rid)]) delete_url = make_confirm_link( url=make_action_link([("mode", "roles"), ("_delete", rid)]), message=_("Do you really want to delete the role %s?") % rid, ) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(clone_url, _("Clone"), "clone") if not role.get("builtin"): html.icon_button(delete_url, _("Delete this role"), "delete") # ID table.cell(_("Name"), rid) # Alias table.cell(_("Alias"), role["alias"]) # Type table.cell(_("Type"), _("builtin") if role.get("builtin") else _("custom")) # Modifications table.cell( _("Modifications"), HTMLWriter.render_span( str(len(role["permissions"])), title=_("That many permissions do not use the factory defaults."), ), ) # Users table.cell( _("Users"), HTML(", ").join( [ HTMLWriter.render_a( user.get("alias", user_id), folder_preserving_link([("mode", "edit_user"), ("edit", user_id)]), ) for (user_id, user) in users.items() if rid in user["roles"] ] ), )
def _find_usages_in_users(self, tpname): used_in = [] for userid, user in userdb.load_users().items(): tp = user.get("notification_period") if tp == tpname: used_in.append(("%s: %s" % (_("User"), userid), watolib.folder_preserving_link([("mode", "edit_user"), ("edit", userid)]))) for index, rule in enumerate(user.get("notification_rules", [])): used_in += self._find_usages_in_notification_rule( tpname, index, rule, user_id=userid) return used_in
def _create_auth_file(callee, users=None): if users is None: users = userdb.load_users() store.mkdir(_auth_base_dir) contactgroups = load_contact_group_information() groups = {} for gid, group in contactgroups.items(): if 'nagvis_maps' in group and group['nagvis_maps']: groups[gid] = group['nagvis_maps'] _create_php_file(callee, users, config.get_role_permissions(), groups)
def page(self): with table_element("roles") as table: users = userdb.load_users() for rid, role in sorted(self._roles.items(), key=lambda a: (a[1]["alias"], a[0])): table.row() # Actions table.cell(_("Actions"), css="buttons") edit_url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", rid)]) clone_url = make_action_link([("mode", "roles"), ("_clone", rid)]) delete_url = make_action_link([("mode", "roles"), ("_delete", rid)]) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(clone_url, _("Clone"), "clone") if not role.get("builtin"): html.icon_button(delete_url, _("Delete this role"), "delete") # ID table.text_cell(_("Name"), rid) # Alias table.text_cell(_("Alias"), role["alias"]) # Type table.cell( _("Type"), _("builtin") if role.get("builtin") else _("custom")) # Modifications table.cell( _("Modifications"), "<span title='%s'>%s</span>" % (_("That many permissions do not use the factory defaults." ), len(role["permissions"]))) # Users table.cell( _("Users"), HTML(", ").join([ html.render_a( user.get("alias", user_id), watolib.folder_preserving_link([ ("mode", "edit_user"), ("edit", user_id) ])) for (user_id, user) in users.items() if rid in user["roles"] ]))
def _show_form(self) -> None: assert user.id is not None users = userdb.load_users() user_spec: Optional[UserSpec] = users.get(user.id) if user_spec 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_spec.get("alias", user.id)) select_language(user_spec) # Let the user configure how he wants to be notified rulebased_notifications = rulebased_notifications_enabled() if ( not rulebased_notifications and user.may("general.edit_notifications") and user_spec.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_spec.get("notification_method") ) if user.may("general.edit_user_attributes"): custom_user_attr_topics = get_user_attributes_by_topic() _show_custom_user_attr(user_spec, custom_user_attr_topics.get("personal", [])) forms.header(_("User interface settings")) _show_custom_user_attr(user_spec, custom_user_attr_topics.get("interface", [])) forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def _show_form(self) -> None: assert user.id is not None users = userdb.load_users() change_reason = request.get_ascii_input("reason") if change_reason == "expired": html.p( _("Your password is too old, you need to choose a new password." )) elif change_reason == "enforced": html.p( _("You are required to change your password before proceeding." )) user_spec = users.get(user.id) if user_spec is None: html.show_warning(_("Sorry, your user account does not exist.")) html.footer() return locked_attributes = userdb.locked_attributes( user_spec.get("connector")) if "password" in locked_attributes: raise MKUserError( "cur_password", _("You can not change your password, because it is " "managed by another system."), ) html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(self._page_title()) forms.section(_("Current Password")) html.password_input("cur_password", autocomplete="new-password") forms.section(_("New Password")) html.password_input("password", autocomplete="new-password") forms.section(_("New Password Confirmation")) html.password_input("password2", autocomplete="new-password") forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def _find_usages_of_contact_group_in_users(name: GroupName) -> List[Tuple[str, str]]: """Is the contactgroup assigned to a user?""" used_in = [] users = userdb.load_users() for userid, user_spec in sorted(users.items(), key=lambda x: x[1].get("alias", x[0])): cgs = user_spec.get("contactgroups", []) if name in cgs: used_in.append( ( "%s: %s" % (_("User"), user_spec.get("alias", userid)), folder_preserving_link([("mode", "edit_user"), ("edit", userid)]), ) ) return used_in
def _from_vars(self): # TODO: Should we turn the both fields below into Optional[UserId]? self._user_id = html.request.get_unicode_input("edit") # missing -> new user self._cloneid = html.request.get_unicode_input("clone") # Only needed in 'new' mode # TODO: Nuke the field below? It effectively hides facts about _user_id for mypy. self._is_new_user = self._user_id is None self._users = userdb.load_users(lock=html.is_transaction()) new_user = userdb.new_user_template('htpasswd') if self._user_id is not None: self._user = self._users.get(UserId(self._user_id), new_user) elif self._cloneid: self._user = self._users.get(UserId(self._cloneid), new_user) else: self._user = new_user self._locked_attributes = userdb.locked_attributes(self._user.get('connector'))
def create_auth_file(callee, users=None): from cmk.gui.watolib.groups import load_contact_group_information import cmk.gui.userdb as userdb # TODO: Cleanup if users is None: users = userdb.load_users() store.mkdir(g_auth_base_dir) contactgroups = load_contact_group_information() groups = {} for gid, group in contactgroups.items(): if 'nagvis_maps' in group and group['nagvis_maps']: groups[gid] = group['nagvis_maps'] create_php_file(callee, users, config.get_role_permissions(), groups)
def list_users(params): """Show all users""" user_collection = { "id": "user", "domainType": "user_config", "value": [ constructors.collection_item( domain_type="user_config", title=attrs["alias"], identifier=user_id, ) for user_id, attrs in userdb.load_users(False).items() ], "links": [constructors.link_rel("self", constructors.collection_href("user_config"))], } return constructors.serve_json(user_collection)
def _from_vars(self): self._user_id = html.get_unicode_input("edit") # missing -> new user self._cloneid = html.get_unicode_input("clone") # Only needed in 'new' mode self._is_new_user = self._user_id is None self._users = userdb.load_users(lock=html.is_transaction()) if self._is_new_user: if self._cloneid: self._user = self._users.get(self._cloneid, userdb.new_user_template('htpasswd')) else: self._user = userdb.new_user_template('htpasswd') else: self._user = self._users.get(self._user_id, userdb.new_user_template('htpasswd')) self._locked_attributes = userdb.locked_attributes(self._user.get('connector'))
def _bulk_delete_users_after_confirm(self): selected_users = [] users = userdb.load_users() for varname, _value in html.request.itervars(prefix="_c_user_"): if html.get_checkbox(varname): user = base64.b64decode(varname.split("_c_user_")[-1]).decode("utf-8") if user in users: selected_users.append(user) if selected_users: c = wato_confirm( _("Confirm deletion of %d users") % len(selected_users), _("Do you really want to delete %d users?") % len(selected_users)) if c: delete_users(selected_users) elif c is False: return ""
def find_usages_of_contact_group(name): # Part 1: Rules used_in = _find_usages_of_group_in_rules( name, ['host_contactgroups', 'service_contactgroups']) # Is the contactgroup assigned to a user? users = userdb.load_users() entries = users.items() for userid, user in sorted(entries, key=lambda x: x[1].get("alias", x[0])): cgs = user.get("contactgroups", []) if name in cgs: used_in.append(('%s: %s' % (_('User'), user.get('alias', userid)), folder_preserving_link([('mode', 'edit_user'), ('edit', userid)]))) global_config = load_configuration_settings() # Used in default_user_profile? config_variable = config_variable_registry['default_user_profile']() domain = config_variable.domain() configured = global_config.get('default_user_profile', {}) default_value = domain().default_globals()["default_user_profile"] if (configured and name in configured['contactgroups']) \ or name in default_value['contactgroups']: used_in.append( ('%s' % (_('Default User Profile')), folder_preserving_link([('mode', 'edit_configvar'), ('varname', 'default_user_profile')]))) # Is the contactgroup used in mkeventd notify (if available)? if 'mkeventd_notify_contactgroup' in config_variable_registry: config_variable = config_variable_registry[ 'mkeventd_notify_contactgroup']() domain = config_variable.domain() configured = global_config.get('mkeventd_notify_contactgroup') default_value = domain().default_globals( )["mkeventd_notify_contactgroup"] if (configured and name == configured) \ or name == default_value: used_in.append(('%s' % (config_variable.valuespec().title()), folder_preserving_link([ ('mode', 'edit_configvar'), ('varname', 'mkeventd_notify_contactgroup') ]))) return used_in
def delete_users(users_to_delete): if config.user.id in users_to_delete: raise MKUserError(None, _("You cannot delete your own account!")) all_users = userdb.load_users(lock=True) deleted_users = [] for entry in users_to_delete: if entry in all_users: # Silently ignore not existing users deleted_users.append(entry) del all_users[entry] else: raise MKUserError(None, _("Unknown user: %s") % entry) if deleted_users: add_change("edit-users", _("Deleted user: %s") % ", ".join(deleted_users)) userdb.save_users(all_users)
def _action(self) -> bool: 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) return True
def _rename_host_in_event_rules(oldname, newname): actions = [] def rename_in_event_rules(rules): num_changed = 0 for rule in rules: for key in ["match_hosts", "match_exclude_hosts"]: if rule.get(key): if rename_host_in_list(rule[key], oldname, newname): num_changed += 1 return num_changed users = userdb.load_users(lock=True) some_user_changed = False for user in users.values(): if unrules := user.get("notification_rules"): if num_changed := rename_in_event_rules(unrules): actions += ["notify_user"] * num_changed some_user_changed = True
def edit_users(changed_users): if user: user.need_permission("wato.users") user.need_permission("wato.edit") all_users = userdb.load_users(lock=True) new_users_info = [] modified_users_info = [] for user_id, settings in changed_users.items(): user_attrs = settings.get("attributes") is_new_user = settings.get("is_new_user", True) _validate_user_attributes(all_users, user_id, user_attrs, is_new_user=is_new_user) if is_new_user: new_users_info.append(user_id) else: modified_users_info.append(user_id) if is_new_user: add_internal_attributes(user_attrs) old_object = make_user_audit_log_object(all_users.get(user_id, {})) log_audit( action="edit-user", message=(_("Created new user: %s") % user_id if is_new_user else _("Modified user: %s") % user_id), diff_text=make_diff_text(old_object, make_user_audit_log_object(user_attrs)), object_ref=make_user_object_ref(user_id), ) all_users[user_id] = user_attrs if new_users_info: add_change("edit-users", _("Created new users: %s") % ", ".join(new_users_info)) if modified_users_info: add_change("edit-users", _("Modified users: %s") % ", ".join(modified_users_info)) userdb.save_users(all_users, datetime.now())