def page(self): if not self._job_snapshot.exists(): # Skip if snapshot doesnt exists pass elif self._job_snapshot.is_active(): # Still running html.message( HTML(_("User synchronization currently running: ")) + self._job_details_link()) url = html.makeuri([]) html.immediate_browser_redirect(2, url) elif self._job_snapshot.state() == gui_background_job.background_job.JobStatusStates.FINISHED \ and not self._job_snapshot.acknowledged_by(): # Just finished, auto-acknowledge userdb.UserSyncBackgroundJob().acknowledge(config.user.id) #html.message(_("User synchronization successful")) elif not self._job_snapshot.acknowledged_by() and self._job_snapshot.has_exception(): # Finished, but not OK - show info message with links to details html.show_warning( HTML(_("Last user synchronization ran into an exception: ")) + self._job_details_link()) self._show_user_list()
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_status(self): job_status = self._get_job_status() html.h3(_("Job status")) if job_status["is_active"]: html.immediate_browser_redirect(0.8, html.makeuri([])) job = FetchAgentOutputBackgroundJob(self._request) gui_background_job.JobRenderer.show_job_details(job.get_job_id(), job_status)
def page(self): job_manager = gui_background_job.GUIBackgroundJobManager() back_url = makeuri_contextless(request, [("mode", "background_jobs_overview")]) job_manager.show_status_of_job_classes(gui_background_job.job_registry.values(), job_details_back_url=back_url) if any( job_manager.get_running_job_ids(c) for c in gui_background_job.job_registry.values()): html.immediate_browser_redirect(0.8, "")
def page(self): job_id = html.request.var("job_id") job = gui_background_job.GUIBackgroundJob(job_id) if not job.exists(): html.message(_("Background job info is not available")) return try: # Race condition, the job might get deleted during snapshot generation job_snapshot = job.get_status_snapshot() except Exception: html.message(_("Background job info is not available")) logger.error(traceback.format_exc()) return job_manager = gui_background_job.GUIBackgroundJobManager() job_manager.show_job_details_from_snapshot(job_snapshot) if job_snapshot.is_running(): html.immediate_browser_redirect(1, "")
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.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.reset_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) 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) 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.show_message(_("Your password has been changed.")) raise HTTPRedirect(html.request.var('_origtarget', 'index.py')) else: html.show_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()
def page_edit(cls): back_url = html.get_url_input("back", cls.list_url()) cls.load() cls.need_overriding_permission("edit") # Three possible modes: # "create" -> create completely new page # "clone" -> like new, but prefill form with values from existing page # "edit" -> edit existing page mode = html.request.var('mode', 'edit') if mode == "create": title = cls.phrase("create") page_dict = { "name": cls.default_name(), "topic": cls.default_topic(), } else: # Load existing page. visual from disk - and create a copy if 'load_user' is set page_name = html.request.var("load_name") if mode == "edit": title = cls.phrase("edit") owner_user_id = UserId( html.request.get_unicode_input_mandatory("owner", config.user.id)) if owner_user_id == config.user.id: page = cls.find_my_page(page_name) else: page = cls.find_foreign_page(owner_user_id, page_name) if page is None: raise MKUserError(None, _("The requested %s does not exist") % cls.phrase("title")) # TODO FIXME: Looks like a hack cls.remove_instance((owner_user_id, page_name)) # will be added later again else: # clone title = cls.phrase("clone") load_user = html.request.get_unicode_input( "load_user") # FIXME: Change varname to "owner" try: page = cls.instance((load_user, page_name)) except KeyError: raise MKUserError(None, _("The requested %s does not exist") % cls.phrase("title")) page_dict = page.internal_representation() html.header(title) html.begin_context_buttons() html.context_button(_("Back"), back_url, "back") html.end_context_buttons() parameters, keys_by_topic = cls._collect_parameters(mode) vs = Dictionary( title=_("General Properties"), render='form', optional_keys=False, elements=parameters, headers=keys_by_topic, ) def validate(page_dict): owner_user_id = UserId(html.request.get_unicode_input_mandatory( "owner", config.user.id)) page_name = page_dict["name"] if owner_user_id == config.user.id: page = cls.find_my_page(page_name) else: page = cls.find_foreign_page(owner_user_id, page_name) if page: raise MKUserError( "_p_name", _("You already have an element with the ID <b>%s</b>") % page_dict["name"]) new_page_dict = forms.edit_valuespec(vs, page_dict, validate=validate, focus="_p_title", method="POST") if new_page_dict is not None: # Take over keys from previous value that are specific to the page type # and not edited here. if mode in ("edit", "clone"): for key, value in page_dict.items(): new_page_dict.setdefault(key, value) owner = UserId(html.request.get_unicode_input_mandatory("owner", config.user.id)) new_page_dict["owner"] = owner new_page = cls(new_page_dict) cls.add_page(new_page) cls.save_user_instances(owner) if mode == "create": redirect_url = new_page.after_create_url() or back_url else: redirect_url = back_url html.immediate_browser_redirect(0.5, redirect_url) html.show_message(_('Your changes haven been saved.')) # Reload sidebar.TODO: This code logically belongs to PageRenderer. How # can we simply move it there? # TODO: This is not true for all cases. e.g. the BookmarkList is not # of type PageRenderer but has a dedicated sidebar snapin. Maybe # the best option would be to make a dedicated method to decide whether # or not to reload the sidebar. if new_page_dict.get("hidden") in [ None, False ] \ or new_page_dict.get("hidden") != page_dict.get("hidden"): html.reload_sidebar() else: html.show_localization_hint() html.footer() return