diff --git a/java/code/src/com/redhat/rhn/domain/notification/NotificationMessage.java b/java/code/src/com/redhat/rhn/domain/notification/NotificationMessage.java index 048f7bd00f06..f6a1a9559b01 100644 --- a/java/code/src/com/redhat/rhn/domain/notification/NotificationMessage.java +++ b/java/code/src/com/redhat/rhn/domain/notification/NotificationMessage.java @@ -25,6 +25,7 @@ import com.redhat.rhn.domain.notification.types.OnboardingFailed; import com.redhat.rhn.domain.notification.types.PaygAuthenticationUpdateFailed; import com.redhat.rhn.domain.notification.types.PaygNotCompliantWarning; +import com.redhat.rhn.domain.notification.types.SCCOptOutWarning; import com.redhat.rhn.domain.notification.types.StateApplyFailed; import com.redhat.rhn.domain.notification.types.SubscriptionWarning; import com.redhat.rhn.domain.notification.types.UpdateAvailable; @@ -141,6 +142,8 @@ public NotificationData getNotificationData() { return new Gson().fromJson(getData(), UpdateAvailable.class); case PaygNotCompliantWarning: return new Gson().fromJson(getData(), PaygNotCompliantWarning.class); + case SCCOptOutWarning: + return new Gson().fromJson(getData(), SCCOptOutWarning.class); default: throw new RhnRuntimeException("Notification type not found"); } } @@ -162,6 +165,7 @@ public String getTypeAsString() { case SubscriptionWarning: return "Subscription Warning"; case UpdateAvailable: return "Updates are Available"; case PaygNotCompliantWarning: return "PAYG instance is not compliant"; + case SCCOptOutWarning: return "SCC Data Sync Disabled"; default: return getType().name(); } } diff --git a/java/code/src/com/redhat/rhn/domain/notification/UserNotificationFactory.java b/java/code/src/com/redhat/rhn/domain/notification/UserNotificationFactory.java index 97b810e74381..91fb9bd7e906 100644 --- a/java/code/src/com/redhat/rhn/domain/notification/UserNotificationFactory.java +++ b/java/code/src/com/redhat/rhn/domain/notification/UserNotificationFactory.java @@ -21,6 +21,7 @@ import com.redhat.rhn.common.messaging.Mail; import com.redhat.rhn.common.messaging.SmtpMail; import com.redhat.rhn.domain.notification.types.NotificationData; +import com.redhat.rhn.domain.notification.types.NotificationType; import com.redhat.rhn.domain.org.Org; import com.redhat.rhn.domain.role.Role; import com.redhat.rhn.domain.user.User; @@ -237,6 +238,22 @@ public static List listAllByUser(User userIn) { return getSession().createQuery(criteria).getResultList(); } + /** + * Fetch the most recent {@link NotificationMessage} of a given type. + * + * @param messageType the type of the notification message + * @return the latest NotificationMessage of the specified type, or null if none found + */ + public static NotificationMessage getLastNotificationMessageByType(NotificationType messageType) { + CriteriaBuilder builder = getSession().getCriteriaBuilder(); + CriteriaQuery criteria = builder.createQuery(NotificationMessage.class); + Root root = criteria.from(NotificationMessage.class); + criteria.where(builder.equal(root.get("type"), messageType)); + criteria.orderBy(builder.desc(root.get("created"))); + List result = getSession().createQuery(criteria).setMaxResults(1).getResultList(); + return result.isEmpty() ? null : result.get(0); + } + /** * Lookup for unread {@link UserNotification}. * diff --git a/java/code/src/com/redhat/rhn/domain/notification/types/NotificationType.java b/java/code/src/com/redhat/rhn/domain/notification/types/NotificationType.java index 0e5739af4fcc..c65cee860b3d 100644 --- a/java/code/src/com/redhat/rhn/domain/notification/types/NotificationType.java +++ b/java/code/src/com/redhat/rhn/domain/notification/types/NotificationType.java @@ -28,4 +28,5 @@ public enum NotificationType { SubscriptionWarning, UpdateAvailable, PaygNotCompliantWarning, + SCCOptOutWarning, } diff --git a/java/code/src/com/redhat/rhn/domain/notification/types/SCCOptOutWarning.java b/java/code/src/com/redhat/rhn/domain/notification/types/SCCOptOutWarning.java new file mode 100644 index 000000000000..6a2ef4f5b021 --- /dev/null +++ b/java/code/src/com/redhat/rhn/domain/notification/types/SCCOptOutWarning.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 SUSE LLC + * + * This software is licensed to you under the GNU General Public License, + * version 2 (GPLv2). There is NO WARRANTY for this software, express or + * implied, including the implied warranties of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 + * along with this software; if not, see + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * Red Hat trademarks are not licensed under GPLv2. No permission is + * granted to use or replicate Red Hat trademarks that are incorporated + * in this software or its documentation. + */ +package com.redhat.rhn.domain.notification.types; + +import com.redhat.rhn.common.localization.LocalizationService; +import com.redhat.rhn.domain.notification.NotificationMessage; + +public class SCCOptOutWarning implements NotificationData { + + private static final LocalizationService LOCALIZATION_SERVICE = LocalizationService.getInstance(); + + @Override + public NotificationMessage.NotificationMessageSeverity getSeverity() { + return NotificationMessage.NotificationMessageSeverity.WARNING; + } + + @Override + public NotificationType getType() { + return NotificationType.SCCOptOutWarning; + } + + @Override + public String getSummary() { + return LOCALIZATION_SERVICE.getMessage("notification.sccoptoutwarning.summary"); + } + + @Override + public String getDetails() { + return LOCALIZATION_SERVICE.getMessage("notification.sccoptoutwarning.detail"); + } +} diff --git a/java/code/src/com/redhat/rhn/frontend/action/satellite/SCCDataForwardingConfigAction.java b/java/code/src/com/redhat/rhn/frontend/action/satellite/SCCDataForwardingConfigAction.java new file mode 100644 index 000000000000..720791be4a34 --- /dev/null +++ b/java/code/src/com/redhat/rhn/frontend/action/satellite/SCCDataForwardingConfigAction.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 SUSE LLC + * + * This software is licensed to you under the GNU General Public License, + * version 2 (GPLv2). There is NO WARRANTY for this software, express or + * implied, including the implied warranties of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 + * along with this software; if not, see + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * Red Hat trademarks are not licensed under GPLv2. No permission is + * granted to use or replicate Red Hat trademarks that are incorporated + * in this software or its documentation. + */ +package com.redhat.rhn.frontend.action.satellite; + +import com.redhat.rhn.common.conf.Config; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.manager.satellite.ConfigureSatelliteCommand; + +/** + * This class extends the {@link BaseConfigAction} class to provide specific command configuration for enabling SCC + * data forwarding. + */ +public class SCCDataForwardingConfigAction extends BaseConfigAction { + /** + * {@inheritDoc} + */ + @Override + protected String getCommandClassName() { + return Config.get().getString( + "web.com.redhat.rhn.frontend.action.satellite.GeneralConfigAction.command", + "com.redhat.rhn.manager.satellite.ConfigureSatelliteCommand" + ); + } + + /** + * {@inheritDoc} + */ + @Override + public ConfigureSatelliteCommand getCommand(User user) { + return (ConfigureSatelliteCommand) super.getCommand(user); + } +} diff --git a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml index ec5e978c35b2..196ea84874ea 100644 --- a/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml +++ b/java/code/src/com/redhat/rhn/frontend/strings/java/StringResource_en_US.xml @@ -9511,6 +9511,22 @@ For a detailed analysis, please refer to the log files. <p>@@PRODUCT_NAME@@ {0} is approaching the end of its lifecycle. Please consider upgrading this server instance before general support ends on <strong>{1}</strong>.</p> <p>For Additional information on how to upgrade @@PRODUCT_NAME@@, please review the section <em>Upgrade</em> of the <em>Installation/Upgrade Guide</em> in the official documentation.</p> + + SCC Data Forwarding enabled successfully. + + + SCC Data Forwarding is already enabled. + + + Data is not being synchronized with SCC + + + + <p>Disabling data synchronizing with SCC will lead to reduced visibility of your managed clients between RMT, SMT, @@PRODUCT_NAME@@ and SCC-directly registered clients. + By synchronizing data, you ensure a uniform view of all registered clients. <a href="/rhn/manager/admin/enable-scc-data-forwarding">Click here to enable data forwarding</a>.</p> + <a href="https://suselinux.fra1.qualtrics.com/jfe/form/SV_0ooNnrY0rYuQScS" target="_blank">Help us improve our services by sharing your reason for opting out</a> + + This action was not executed because its earliest execution date was too old. When more than {0} hours pass between the scheduling and the picking up, the action is discarded because it is considered no longer relevant. Please reschedule this action if you really want it to be executed. diff --git a/java/code/src/com/redhat/rhn/taskomatic/task/ForwardRegistrationTask.java b/java/code/src/com/redhat/rhn/taskomatic/task/ForwardRegistrationTask.java index fbb9e475b06d..34a647c9b7fb 100644 --- a/java/code/src/com/redhat/rhn/taskomatic/task/ForwardRegistrationTask.java +++ b/java/code/src/com/redhat/rhn/taskomatic/task/ForwardRegistrationTask.java @@ -19,6 +19,11 @@ import com.redhat.rhn.common.conf.ConfigDefaults; import com.redhat.rhn.domain.credentials.CredentialsFactory; import com.redhat.rhn.domain.credentials.SCCCredentials; +import com.redhat.rhn.domain.notification.NotificationMessage; +import com.redhat.rhn.domain.notification.UserNotificationFactory; +import com.redhat.rhn.domain.notification.types.NotificationType; +import com.redhat.rhn.domain.notification.types.SCCOptOutWarning; +import com.redhat.rhn.domain.role.RoleFactory; import com.redhat.rhn.domain.scc.SCCCachingFactory; import com.redhat.rhn.domain.scc.SCCRegCacheItem; import com.redhat.rhn.manager.content.ContentSyncManager; @@ -29,11 +34,14 @@ import com.suse.scc.client.SCCWebClient; import com.suse.scc.model.SCCVirtualizationHostJson; +import org.apache.commons.lang3.time.DateUtils; import org.quartz.JobExecutionContext; import java.net.URI; import java.net.URISyntaxException; import java.time.LocalDateTime; +import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; @@ -53,6 +61,16 @@ public String getConfigNamespace() { @Override public void execute(JobExecutionContext arg0) { if (!ConfigDefaults.get().isForwardRegistrationEnabled()) { + NotificationMessage lastNotification = UserNotificationFactory + .getLastNotificationMessageByType(NotificationType.SCCOptOutWarning); + + if (lastNotification == null || lastNotification.getCreated().before(DateUtils.addMonths(new Date(), -3))) { + NotificationMessage notificationMessage = + UserNotificationFactory.createNotificationMessage(new SCCOptOutWarning()); + UserNotificationFactory.storeNotificationMessageFor(notificationMessage, + Collections.singleton(RoleFactory.ORG_ADMIN), Optional.empty()); + } + if (GlobalInstanceHolder.PAYG_MANAGER.isPaygInstance() && GlobalInstanceHolder.PAYG_MANAGER.hasSCCCredentials()) { log.warn("SUSE Manager PAYG instances must forward registration data to SCC when " + diff --git a/java/code/src/com/suse/manager/webui/Router.java b/java/code/src/com/suse/manager/webui/Router.java index ffc0dd911478..24d16c8c27ce 100644 --- a/java/code/src/com/suse/manager/webui/Router.java +++ b/java/code/src/com/suse/manager/webui/Router.java @@ -68,6 +68,7 @@ import com.suse.manager.webui.controllers.activationkeys.ActivationKeysViewsController; import com.suse.manager.webui.controllers.admin.AdminApiController; import com.suse.manager.webui.controllers.admin.AdminViewsController; +import com.suse.manager.webui.controllers.admin.EnableSCCDataForwardingController; import com.suse.manager.webui.controllers.appstreams.AppStreamsController; import com.suse.manager.webui.controllers.bootstrap.RegularMinionBootstrapper; import com.suse.manager.webui.controllers.bootstrap.SSHMinionBootstrapper; @@ -200,6 +201,8 @@ public void init() { // Recurring Action RecurringActionController.initRoutes(jade); + EnableSCCDataForwardingController.initRoutes(jade); + // Subscription Matching SubscriptionMatchingController.initRoutes(jade); diff --git a/java/code/src/com/suse/manager/webui/controllers/admin/EnableSCCDataForwardingController.java b/java/code/src/com/suse/manager/webui/controllers/admin/EnableSCCDataForwardingController.java new file mode 100644 index 000000000000..2ec4931fddd3 --- /dev/null +++ b/java/code/src/com/suse/manager/webui/controllers/admin/EnableSCCDataForwardingController.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 SUSE LLC + * + * This software is licensed to you under the GNU General Public License, + * version 2 (GPLv2). There is NO WARRANTY for this software, express or + * implied, including the implied warranties of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 + * along with this software; if not, see + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * Red Hat trademarks are not licensed under GPLv2. No permission is + * granted to use or replicate Red Hat trademarks that are incorporated + * in this software or its documentation. + */ +package com.suse.manager.webui.controllers.admin; + +import static com.suse.manager.webui.utils.SparkApplicationHelper.withUser; +import static spark.Spark.get; + +import com.redhat.rhn.common.conf.ConfigDefaults; +import com.redhat.rhn.common.localization.LocalizationService; +import com.redhat.rhn.common.security.PermissionException; +import com.redhat.rhn.common.validator.ValidatorError; +import com.redhat.rhn.domain.role.RoleFactory; +import com.redhat.rhn.domain.user.User; +import com.redhat.rhn.frontend.action.satellite.SCCDataForwardingConfigAction; +import com.redhat.rhn.manager.satellite.ConfigureSatelliteCommand; + +import java.util.HashMap; +import java.util.Map; + +import spark.ModelAndView; +import spark.Request; +import spark.Response; +import spark.template.jade.JadeTemplateEngine; + +/** + * Controller class providing backend code to enable SCC data forwarding. + */ +public class EnableSCCDataForwardingController { + + private EnableSCCDataForwardingController() { } + + private static final SCCDataForwardingConfigAction CONFIG_ACTION = new SCCDataForwardingConfigAction(); + + /** + * Initializes the routes. + * + * @param jade the jade engine + */ + public static void initRoutes(JadeTemplateEngine jade) { + get("/manager/admin/enable-scc-data-forwarding", withUser(EnableSCCDataForwardingController::enable), jade); + } + + /** + * Route to enable data forwarding + * @param request - the request + * @param response - the response + * @param user - the user + * @return - jade template with confirmation message + */ + public static ModelAndView enable(Request request, Response response, User user) { + String message = LocalizationService.getInstance().getMessage("scc-data-forwarding.enabled"); + + if (!user.hasRole(RoleFactory.ORG_ADMIN)) { + throw new PermissionException("Only Org Admins can change SCC data forwarding property."); + } + + if (ConfigDefaults.get().isForwardRegistrationEnabled()) { + message = LocalizationService.getInstance().getMessage("scc-data-forwarding.not-changed"); + } + else { + ConfigureSatelliteCommand csc = CONFIG_ACTION.getCommand(user); + csc.updateBoolean(ConfigDefaults.FORWARD_REGISTRATION, Boolean.TRUE); + ValidatorError[] verrors = csc.storeConfiguration(); + if (verrors != null && verrors.length > 0) { + StringBuilder errorMsg = new StringBuilder(); + errorMsg.append("The following errors happened when enabling SCC data forwarding:\n"); + for (var error: verrors) { + errorMsg.append(error.getLocalizedMessage()); + } + message = errorMsg.toString(); + } + } + + Map data = new HashMap<>(); + data.put("message", message); + return new ModelAndView(data, "templates/admin/enable-scc-data-forwarding-confirm.jade"); + } +} diff --git a/java/code/src/com/suse/manager/webui/templates/admin/enable-scc-data-forwarding-confirm.jade b/java/code/src/com/suse/manager/webui/templates/admin/enable-scc-data-forwarding-confirm.jade new file mode 100644 index 000000000000..5c254ca9f89d --- /dev/null +++ b/java/code/src/com/suse/manager/webui/templates/admin/enable-scc-data-forwarding-confirm.jade @@ -0,0 +1,3 @@ +h1 #{message} +p + a(href="/rhn/manager/notification-messages") Return to notifications diff --git a/java/spacewalk-java.changes.welder.scc-data-forwarding-warning b/java/spacewalk-java.changes.welder.scc-data-forwarding-warning new file mode 100644 index 000000000000..7ea89d278430 --- /dev/null +++ b/java/spacewalk-java.changes.welder.scc-data-forwarding-warning @@ -0,0 +1,2 @@ +- Add notification for users with disabled SCC data forwarding + (jsc#SUMA-431) diff --git a/web/html/src/manager/notifications/notification-messages.tsx b/web/html/src/manager/notifications/notification-messages.tsx index 4c7031943fd4..3d9dd7945824 100644 --- a/web/html/src/manager/notifications/notification-messages.tsx +++ b/web/html/src/manager/notifications/notification-messages.tsx @@ -59,6 +59,10 @@ const _MESSAGE_TYPE = { id: "PaygNotCompliantWarning", text: t("PAYG instance is not compliant"), }, + SCCOptOutWarning: { + id: "SCCOptOutWarning", + text: t("SCC Data Sync Disabled"), + }, }; function reloadData(dataUrlSlice: string) { diff --git a/web/spacewalk-web.changes.welder.scc-data-forwarding-warning b/web/spacewalk-web.changes.welder.scc-data-forwarding-warning new file mode 100644 index 000000000000..7ea89d278430 --- /dev/null +++ b/web/spacewalk-web.changes.welder.scc-data-forwarding-warning @@ -0,0 +1,2 @@ +- Add notification for users with disabled SCC data forwarding + (jsc#SUMA-431)