Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notification for users with disabled SCC data forwarding (jsc#SUMA-431) #9582

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
}
}
Expand All @@ -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();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -237,6 +238,22 @@ public static List<UserNotification> 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<NotificationMessage> criteria = builder.createQuery(NotificationMessage.class);
Root<NotificationMessage> root = criteria.from(NotificationMessage.class);
criteria.where(builder.equal(root.get("type"), messageType));
criteria.orderBy(builder.desc(root.get("created")));
List<NotificationMessage> result = getSession().createQuery(criteria).setMaxResults(1).getResultList();
return result.isEmpty() ? null : result.get(0);
}

/**
* Lookup for unread {@link UserNotification}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ public enum NotificationType {
SubscriptionWarning,
UpdateAvailable,
PaygNotCompliantWarning,
SCCOptOutWarning,
}
Original file line number Diff line number Diff line change
@@ -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");
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9511,6 +9511,22 @@ For a detailed analysis, please refer to the log files.</source>
<source>&lt;p&gt;@@PRODUCT_NAME@@ {0} is approaching the end of its lifecycle. Please consider upgrading this server instance before general support ends on &lt;strong&gt;{1}&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For Additional information on how to upgrade @@PRODUCT_NAME@@, please review the section &lt;em&gt;Upgrade&lt;/em&gt; of the &lt;em&gt;Installation/Upgrade Guide&lt;/em&gt; in the official documentation.&lt;/p&gt;</source>
</trans-unit>
<trans-unit id="scc-data-forwarding.enabled">
<source>SCC Data Forwarding enabled successfully.</source>
</trans-unit>
<trans-unit id="scc-data-forwarding.not-changed">
<source>SCC Data Forwarding is already enabled.</source>
</trans-unit>
<trans-unit id="notification.sccoptoutwarning.summary">
<source>Data is not being synchronized with SCC</source>
</trans-unit>
<trans-unit id="notification.sccoptoutwarning.detail" xml:space="preserve">
<source>
&lt;p&gt;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. &lt;a href="/rhn/manager/admin/enable-scc-data-forwarding"&gt;Click here to enable data forwarding&lt;/a&gt;.&lt;/p&gt;
&lt;a href="https://suselinux.fra1.qualtrics.com/jfe/form/SV_0ooNnrY0rYuQScS" target="_blank"&gt;Help us improve our services by sharing your reason for opting out&lt;/a&gt;
</source>
</trans-unit>
<trans-unit id="task.action.rejection.reason">
<source>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.</source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 " +
Expand Down
3 changes: 3 additions & 0 deletions java/code/src/com/suse/manager/webui/Router.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -200,6 +201,8 @@ public void init() {
// Recurring Action
RecurringActionController.initRoutes(jade);

EnableSCCDataForwardingController.initRoutes(jade);

// Subscription Matching
SubscriptionMatchingController.initRoutes(jade);

Expand Down
Original file line number Diff line number Diff line change
@@ -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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the change also reflected in the file(rhn.conf? )?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more question. We are only changing the property here but if some user actually disabled the taskomatic job, we don't take care of enabling that here, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the change also reflected in the file(rhn.conf? )?

Yes, it does.

One more question. We are only changing the property here but if some user actually disabled the taskomatic job, we don't take care of enabling that here, right?

If the Taskomatic job is disabled, the user won’t receive the notification because it is created inside the job. We could create a different job specifically for the notification; however, it would still be possible for the user to disable this specific job. So, I don’t think it’s worth it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the taskomatic job: I think one thing that we could consider doing here is resetting the schedule to the default one (the one you have after installation), just in case someone might have changed it to only run once per month or so? Not a blocker for this PR though, if it turns out to be complex we can skip it for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly we have a different problem. You cannot "disable" a job. In fact it is removed and you cannot get it back. I think we have a separate issue or bug report about it. This problem is bigger than just a changed schedule

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for the pointer Michael, that one is concerning :(

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<String, Object> data = new HashMap<>();
data.put("message", message);
return new ModelAndView(data, "templates/admin/enable-scc-data-forwarding-confirm.jade");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
h1 #{message}
p
a(href="/rhn/manager/notification-messages") Return to notifications
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add notification for users with disabled SCC data forwarding
(jsc#SUMA-431)
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions web/spacewalk-web.changes.welder.scc-data-forwarding-warning
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Add notification for users with disabled SCC data forwarding
(jsc#SUMA-431)
Loading