def _page_menu_entries_related(page_name: str) -> Iterator[PageMenuEntry]: if page_name != "user_change_pw": yield PageMenuEntry( title=_("Change password"), icon_name="topic_change_password", item=make_simple_link("user_change_pw.py"), is_shortcut=True, ) if page_name != "user_two_factor_overview" and user.may( "general.manage_2fa"): yield PageMenuEntry( title=_("Edit two-factor authentication"), icon_name="topic_2fa", item=make_simple_link("user_two_factor_overview.py"), is_shortcut=True, ) if page_name != "user_profile": yield PageMenuEntry( title=_("Edit profile"), icon_name="topic_profile", item=make_simple_link("user_profile.py"), is_shortcut=True, ) if (page_name != "user_notifications_p" and rulebased_notifications_enabled() and user.may("general.edit_notifications")): yield PageMenuEntry( title=_("Notification rules"), icon_name="topic_events", item=make_simple_link("wato.py?mode=user_notifications_p"), is_shortcut=True, )
def execute(self) -> Iterator[ACResult]: if not rulebased_notifications_enabled(): yield ACResultCRIT( 'Rulebased notifications are deactivated in the global settings' ) else: yield ACResultOK(_("Rulebased notifications are activated"))
def _show_form(self, profile_changed: bool) -> None: assert config.user.id is not None users = userdb.load_users() if profile_changed: html.reload_sidebar() html.show_message(_("Successfully updated user profile.")) # Ensure theme changes are applied without additional user interaction html.immediate_browser_redirect(0.5, makeuri(global_request, [])) 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(self._page_title()) 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'): 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)) forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def _show_context_buttons(self) -> None: rulebased_notifications = rulebased_notifications_enabled() 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()
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 _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 _user_menu_topics() -> List[TopicMenuTopic]: items = [ TopicMenuItem( name="change_password", title=_("Change password"), url="user_change_pw.py", sort_index=10, is_advanced=False, icon_name="topic_change_password", emblem=None, ), TopicMenuItem( name="user_profile", title=_("Edit profile"), url="user_profile.py", sort_index=20, is_advanced=False, icon_name="topic_profile", emblem=None, ), TopicMenuItem( name="logout", title=_("Logout"), url="logout.py", sort_index=30, is_advanced=False, icon_name="sidebar_logout", emblem=None, ), ] if rulebased_notifications_enabled() and config.user.may('general.edit_notifications'): items.insert( 1, TopicMenuItem( name="notification_rules", title=_("Notification rules"), url="wato.py?mode=user_notifications_p", sort_index=30, is_advanced=False, icon_name="topic_events", emblem=None, )) return [TopicMenuTopic( name="user", title=_("User"), icon_name="topic_profile", items=items, )]
def _page_menu_entries_related() -> Iterator[PageMenuEntry]: yield PageMenuEntry( title=_("Change password"), icon_name="topic_change_password", item=make_simple_link("user_change_pw.py"), ) yield PageMenuEntry( title=_("Edit profile"), icon_name="topic_profile", item=make_simple_link("user_profile.py"), ) if rulebased_notifications_enabled() and config.user.may('general.edit_notifications'): yield PageMenuEntry( title=_("Notification rules"), icon_name="topic_events", item=make_simple_link("wato.py?mode=user_notifications_p"), )
def _validate_user_attributes(all_users, user_id, user_attrs, is_new_user=True): # Check user_id if is_new_user: if user_id in all_users: raise MKUserError( "user_id", _("This username is already being used by another user.")) vs_user_id = UserID(allow_empty=False) vs_user_id.validate_value(user_id, "user_id") else: if user_id not in all_users: raise MKUserError( None, _("The user you are trying to edit does not exist.")) # Full name alias = user_attrs.get("alias") if not alias: raise MKUserError( "alias", _("Please specify a full name or descriptive alias for the user.")) # Locking locked = user_attrs.get("locked") if user_id == config.user.id and locked: raise MKUserError("locked", _("You cannot lock your own account!")) # Authentication: Password or Secret if "automation_secret" in user_attrs: secret = user_attrs["automation_secret"] if len(secret) < 10: raise MKUserError( 'secret', _("Please specify a secret of at least 10 characters length.")) else: password = user_attrs.get("password") if password: verify_password_policy(password) # Email email = user_attrs.get("email") vs_email = EmailAddress() vs_email.validate_value(email, "email") # Idle timeout idle_timeout = user_attrs.get("idle_timeout") vs_user_idle_timeout = get_vs_user_idle_timeout() vs_user_idle_timeout.validate_value(idle_timeout, "idle_timeout") # Notification settings are only active if we do *not* have rule based notifications! if not global_settings.rulebased_notifications_enabled(): # Notifications notifications_enabled = user_attrs.get("notification_enabled") # Check if user can receive notifications if notifications_enabled: if not email: raise MKUserError( "email", _('You have enabled the notifications but missed to configure a ' 'Email address. You need to configure your mail address in order ' 'to be able to receive emails.')) contactgroups = user_attrs.get("contactgroups") if not contactgroups: raise MKUserError( "notifications_enabled", _('You have enabled the notifications but missed to make the ' 'user member of at least one contact group. You need to make ' 'the user member of a contact group which has hosts assigned ' 'in order to be able to receive emails.')) roles = user_attrs.get("roles") if not roles: raise MKUserError( "role_user", _("Your user has no roles. Please assign at least one role." )) notification_method = user_attrs.get("notification_method") get_vs_flexible_notifications().validate_value(notification_method, "notification_method") else: fallback_contact = user_attrs.get("fallback_contact") if fallback_contact and not email: raise MKUserError( "email", _("You have enabled the fallback notifications but missed to configure an " "email address. You need to configure your mail address in order " "to be able to receive fallback notifications.")) # Custom user attributes for name, attr in userdb.get_user_attributes(): value = user_attrs.get(name) attr.valuespec().validate_value(value, "ua_" + name)
def _user_menu_topics() -> List[TopicMenuTopic]: quick_items = [ TopicMenuItem( name="ui_theme", title=_("Color theme"), url= 'javascript:cmk.sidebar.toggle_user_attribute("ajax_ui_theme.py")', target="", sort_index=10, icon="color_mode", button_title=_get_current_theme_titel(), ), TopicMenuItem( name="sidebar_position", title=_("Sidebar position"), url= 'javascript:cmk.sidebar.toggle_user_attribute("ajax_sidebar_position.py")', target="", sort_index=20, icon="sidebar_position", button_title=_sidebar_position_title(_get_sidebar_position()), ), ] items = [ TopicMenuItem( name="user_profile", title=_("Edit profile"), url="user_profile.py", sort_index=10, icon="topic_profile", ), TopicMenuItem( name="change_password", title=_("Change password"), url="user_change_pw.py", sort_index=30, icon="topic_change_password", ), TopicMenuItem( name="two_factor", title=_("Two-factor authentication"), url="user_two_factor_overview.py", sort_index=30, icon="topic_two_factor", ), TopicMenuItem( name="logout", title=_("Logout"), url="logout.py", sort_index=40, icon="sidebar_logout", ), ] if rulebased_notifications_enabled() and user.may( "general.edit_notifications"): items.insert( 1, TopicMenuItem( name="notification_rules", title=_("Notification rules"), url="wato.py?mode=user_notifications_p", sort_index=20, icon="topic_events", ), ) return [ TopicMenuTopic( name="user", title=_("User interface"), icon="topic_user_interface", items=quick_items, ), TopicMenuTopic( name="user", title=_("User profile"), icon="topic_profile", items=items, ), ]
def _user_menu_topics() -> List[TopicMenuTopic]: quick_items = [ TopicMenuItem( name="ui_theme", title=_("Interface theme"), url= "javascript:cmk.sidebar.toggle_user_attribute(\"ajax_ui_theme.py\")", target="", sort_index=10, icon="color_mode", button_title=_get_current_theme_titel(), ), TopicMenuItem( name="sidebar_position", title=_("Sidebar position"), url= "javascript:cmk.sidebar.toggle_user_attribute(\"ajax_sidebar_position.py\")", target="", sort_index=20, icon="sidebar_position", button_title=_sidebar_position_title(_get_sidebar_position()), ), ] items = [ TopicMenuItem( name="change_password", title=_("Change password"), url="user_change_pw.py", sort_index=10, icon="topic_change_password", ), TopicMenuItem( name="user_profile", title=_("Edit profile"), url="user_profile.py", sort_index=20, icon="topic_profile", ), TopicMenuItem( name="logout", title=_("Logout"), url="logout.py", sort_index=30, icon="sidebar_logout", ), ] if rulebased_notifications_enabled() and config.user.may( 'general.edit_notifications'): items.insert( 1, TopicMenuItem( name="notification_rules", title=_("Notification rules"), url="wato.py?mode=user_notifications_p", sort_index=30, icon="topic_events", )) return [ TopicMenuTopic( name="user", title=_("Quick toggle"), # TODO(rb): set correct icon icon="topic_profile", items=quick_items, ), TopicMenuTopic( name="user", title=_("Profile"), icon="topic_profile", items=items, ) ]
def _show_user_list(self): visible_custom_attrs = [(name, attr) for name, attr in userdb.get_user_attributes() if attr.show_in_table()] users = userdb.load_users() entries = list(users.items()) html.begin_form("bulk_delete_form", method="POST") roles = userdb_utils.load_roles() timeperiods = watolib.timeperiods.load_timeperiods() contact_groups = load_contact_group_information() with table_element("users", None, empty_text=_("No users are defined yet.")) as table: online_threshold = time.time() - config.user_online_maxage for uid, user in sorted( entries, key=lambda x: x[1].get("alias", x[0]).lower()): table.row() # Checkboxes table.cell(html.render_input( "_toggle_group", type_="button", class_="checkgroup", onclick="cmk.selection.toggle_all_rows();", value='X'), sortable=False, css="checkbox") if uid != config.user.id: html.checkbox( "_c_user_%s" % ensure_str(base64.b64encode(uid.encode("utf-8")))) user_connection_id = cleanup_connection_id( user.get('connector')) connection = get_connection(user_connection_id) # Buttons table.cell(_("Actions"), css="buttons") if connection: # only show edit buttons when the connector is available and enabled edit_url = watolib.folder_preserving_link([("mode", "edit_user"), ("edit", uid)]) html.icon_button(edit_url, _("Properties"), "edit") clone_url = watolib.folder_preserving_link([ ("mode", "edit_user"), ("clone", uid) ]) html.icon_button(clone_url, _("Create a copy of this user"), "clone") delete_url = make_action_link([("mode", "users"), ("_delete", uid)]) html.icon_button(delete_url, _("Delete"), "delete") notifications_url = watolib.folder_preserving_link([ ("mode", "user_notifications"), ("user", uid) ]) if rulebased_notifications_enabled(): html.icon_button( notifications_url, _("Custom notification table of this user"), "notifications") # ID table.cell(_("ID"), uid) # Online/Offline if config.save_user_access_times: last_seen = user.get('last_seen', 0) if last_seen >= online_threshold: title = _('Online') img_txt = 'online' elif last_seen != 0: title = _('Offline') img_txt = 'offline' elif last_seen == 0: title = _('Never logged in') img_txt = 'inactive' title += ' (%s %s)' % (render.date(last_seen), render.time_of_day(last_seen)) table.cell(_("Act.")) html.icon(title, img_txt) table.cell(_("Last seen")) if last_seen != 0: html.write_text("%s %s" % (render.date(last_seen), render.time_of_day(last_seen))) else: html.write_text(_("Never logged in")) if cmk_version.is_managed_edition(): table.cell(_("Customer"), managed.get_customer_name(user)) # Connection if connection: table.cell( _("Connection"), '%s (%s)' % (connection.short_title(), user_connection_id)) locked_attributes = userdb.locked_attributes( user_connection_id) else: table.cell( _("Connection"), "%s (%s) (%s)" % (_("UNKNOWN"), user_connection_id, _("disabled")), css="error") locked_attributes = [] # Authentication if "automation_secret" in user: auth_method = _("Automation") elif user.get("password") or 'password' in locked_attributes: auth_method = _("Password") else: auth_method = "<i>%s</i>" % _("none") table.cell(_("Authentication"), auth_method) table.cell(_("State")) if user.get("locked", False): html.icon(_('The login is currently locked'), 'user_locked') if "disable_notifications" in user and isinstance( user["disable_notifications"], bool): disable_notifications_opts = { "disable": user["disable_notifications"] } else: disable_notifications_opts = user.get( "disable_notifications", {}) if disable_notifications_opts.get("disable", False): html.icon(_('Notifications are disabled'), 'notif_disabled') # Full name / Alias table.text_cell(_("Alias"), user.get("alias", "")) # Email table.text_cell(_("Email"), user.get("email", "")) # Roles table.cell(_("Roles")) if user.get("roles", []): role_links = [(watolib.folder_preserving_link([ ("mode", "edit_role"), ("edit", role) ]), roles[role].get("alias")) for role in user["roles"]] html.write_html( HTML(", ").join( html.render_a(alias, href=link) for (link, alias) in role_links)) # contact groups table.cell(_("Contact groups")) cgs = user.get("contactgroups", []) if cgs: cg_aliases = [ contact_groups[c]['alias'] if c in contact_groups else c for c in cgs ] cg_urls = [ watolib.folder_preserving_link([("mode", "edit_contact_group"), ("edit", c)]) for c in cgs ] html.write_html( HTML(", ").join( html.render_a(content, href=url) for (content, url) in zip(cg_aliases, cg_urls))) else: html.i(_("none")) #table.cell(_("Sites")) #html.write(vs_authorized_sites().value_to_text(user.get("authorized_sites", # vs_authorized_sites().default_value()))) # notifications if not rulebased_notifications_enabled(): table.cell(_("Notifications")) if not cgs: html.i(_("not a contact")) elif not user.get("notifications_enabled", True): html.write_text(_("disabled")) elif user.get("host_notification_options", "") == "" and \ user.get("service_notification_options", "") == "": html.write_text(_("all events disabled")) else: tp = user.get("notification_period", "24X7") if tp not in timeperiods: tp = tp + _(" (invalid)") elif tp not in watolib.timeperiods.builtin_timeperiods( ): url = watolib.folder_preserving_link([ ("mode", "edit_timeperiod"), ("edit", tp) ]) tp = html.render_a(timeperiod_spec_alias( timeperiods[tp], tp), href=url) else: tp = timeperiod_spec_alias(timeperiods[tp], tp) html.write(tp) # the visible custom attributes for name, attr in visible_custom_attrs: vs = attr.valuespec() table.cell(escaping.escape_attribute(_u(vs.title()))) html.write( vs.value_to_text(user.get(name, vs.default_value()))) html.button("_bulk_delete_users", _("Bulk Delete"), "submit", style="margin-top:10px") html.hidden_fields() html.end_form() if not load_contact_group_information(): url = "wato.py?mode=contact_groups" html.open_div(class_="info") html.write( _("Note: you haven't defined any contact groups yet. If you <a href='%s'>" "create some contact groups</a> you can assign users to them und thus " "make them monitoring contacts. Only monitoring contacts can receive " "notifications.") % url) html.write( " you can assign users to them und thus " "make them monitoring contacts. Only monitoring contacts can receive " "notifications.") html.close_div()
def _rbn_enabled(self): # Check if rule based notifications are enabled (via WATO) return rulebased_notifications_enabled()