Skip to content

Commit 62ae729

Browse files
Add configuration for who should get licensing notifications #208 (#216)
* added LicensingNotificationConfigurationSource for managing notification settings * added notifiedGroups property to LicensingNotificationClass for user group notifications * updated LicensingConfig.xml and Translations files for new notification settings * added a notification groups section to the end of the licensing admin section * added script service for getting the notification groups list * added tests * removed admin and programming rights restriction for notifications * modified notification message for non admin/programming users
1 parent 271e75b commit 62ae729

File tree

20 files changed

+885
-73
lines changed

20 files changed

+885
-73
lines changed

application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/LicensingConfiguration.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@
2020
package com.xwiki.licensing;
2121

2222
import java.io.File;
23+
import java.util.ArrayList;
24+
import java.util.HashSet;
2325
import java.util.List;
26+
import java.util.Set;
2427

2528
import org.xwiki.component.annotation.Role;
29+
import org.xwiki.stability.Unstable;
2630

2731
/**
2832
* Configuration of the licensing module.
@@ -80,4 +84,35 @@ public interface LicensingConfiguration
8084
* @return the email of the licensing owner or null if the value of the property is not filled up
8185
*/
8286
String getLicensingOwnerEmail();
87+
88+
/**
89+
* @return {@link List} with the groups whose members need to be notified about the extension
90+
* @since 1.31
91+
*/
92+
@Unstable
93+
default List<String> getNotifiedGroups()
94+
{
95+
return new ArrayList<>();
96+
}
97+
98+
/**
99+
* @return {@link Set} with the groups whose members need to be notified about the extension
100+
* @since 1.31
101+
*/
102+
@Unstable
103+
default Set<String> getNotifiedGroupsSet()
104+
{
105+
return new HashSet<>();
106+
}
107+
108+
/**
109+
* @return {@code true} if the context user is member of the groups from {@link #getNotifiedGroups}, or
110+
* {@code false} otherwise
111+
* @since 1.31
112+
*/
113+
@Unstable
114+
default boolean isMemberOfNotifiedGroups()
115+
{
116+
return false;
117+
}
83118
}

application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/DefaultLicensingConfiguration.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
package com.xwiki.licensing.internal;
2121

2222
import java.io.File;
23+
import java.util.ArrayList;
2324
import java.util.Collections;
2425
import java.util.List;
2526
import java.util.Objects;
27+
import java.util.Set;
2628
import java.util.stream.Collectors;
2729

2830
import javax.inject.Inject;
@@ -33,8 +35,13 @@
3335
import org.xwiki.component.annotation.Component;
3436
import org.xwiki.configuration.ConfigurationSource;
3537
import org.xwiki.environment.Environment;
38+
import org.xwiki.model.reference.DocumentReference;
39+
import org.xwiki.model.reference.DocumentReferenceResolver;
3640

41+
import com.xpn.xwiki.XWiki;
42+
import com.xpn.xwiki.XWikiContext;
3743
import com.xwiki.licensing.LicensingConfiguration;
44+
import com.xwiki.licensing.internal.helpers.LicensingNotificationConfigurationSource;
3845

3946
/**
4047
* Default implementation of {@link LicensingConfiguration}.
@@ -74,6 +81,17 @@ public class DefaultLicensingConfiguration implements LicensingConfiguration
7481
@Named("LicensingOwnerConfigurationSource")
7582
private ConfigurationSource ownerConfig;
7683

84+
@Inject
85+
@Named(LicensingNotificationConfigurationSource.HINT)
86+
private ConfigurationSource notificationConfig;
87+
88+
@Inject
89+
@Named("current")
90+
private DocumentReferenceResolver<String> referenceResolver;
91+
92+
@Inject
93+
private Provider<XWikiContext> wikiContextProvider;
94+
7795
private File localStorePath;
7896

7997
@Override
@@ -137,6 +155,28 @@ public String getStoreRenewURL()
137155
return this.storeConfig.getProperty("storeRenewURL");
138156
}
139157

158+
@Override
159+
public List<String> getNotifiedGroups()
160+
{
161+
return convertObjectToStringList(notificationConfig.getProperty("notifiedGroups", new ArrayList<>()));
162+
}
163+
164+
@Override
165+
public Set<String> getNotifiedGroupsSet()
166+
{
167+
return getNotifiedGroups().stream().map(referenceResolver::resolve).map(DocumentReference::toString)
168+
.collect(Collectors.toSet());
169+
}
170+
171+
@Override
172+
public boolean isMemberOfNotifiedGroups()
173+
{
174+
List<String> notifiedGroups = getNotifiedGroups();
175+
XWikiContext wikiContext = wikiContextProvider.get();
176+
XWiki wiki = wikiContext.getWiki();
177+
return notifiedGroups.stream().anyMatch(group -> wiki.getUser(wikiContext).isUserInGroup(group));
178+
}
179+
140180
@SuppressWarnings("unchecked")
141181
private List<String> convertObjectToStringList(Object list)
142182
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package com.xwiki.licensing.internal.helpers;
21+
22+
import java.util.Arrays;
23+
import java.util.List;
24+
25+
import javax.inject.Named;
26+
import javax.inject.Singleton;
27+
28+
import org.xwiki.component.annotation.Component;
29+
import org.xwiki.configuration.internal.AbstractDocumentConfigurationSource;
30+
import org.xwiki.model.reference.DocumentReference;
31+
import org.xwiki.model.reference.LocalDocumentReference;
32+
33+
/**
34+
* Configuration source for notification information.
35+
*
36+
* @version $Id$
37+
* @since 1.31
38+
*/
39+
@Component
40+
@Named(LicensingNotificationConfigurationSource.HINT)
41+
@Singleton
42+
public class LicensingNotificationConfigurationSource extends AbstractDocumentConfigurationSource
43+
{
44+
/**
45+
* Component hint.
46+
*/
47+
public static final String HINT = "LicensingNotificationConfigurationSource";
48+
49+
protected static final List<String> CODE_SPACE = Arrays.asList("Licenses", "Code");
50+
51+
protected static final LocalDocumentReference LICENSING_CONFIG_DOC =
52+
new LocalDocumentReference(CODE_SPACE, "LicensingConfig");
53+
54+
protected static final LocalDocumentReference OWNER_CLASS =
55+
new LocalDocumentReference(CODE_SPACE, "LicensingNotificationClass");
56+
57+
@Override
58+
protected DocumentReference getDocumentReference()
59+
{
60+
return new DocumentReference(LICENSING_CONFIG_DOC, this.getCurrentWikiReference());
61+
}
62+
63+
@Override
64+
protected LocalDocumentReference getClassReference()
65+
{
66+
return OWNER_CLASS;
67+
}
68+
69+
@Override
70+
protected String getCacheId()
71+
{
72+
return "licensing.configuration.notification";
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package com.xwiki.licensing.internal.upgrades;
21+
22+
import java.util.HashSet;
23+
import java.util.Set;
24+
25+
import org.xwiki.eventstream.TargetableEvent;
26+
27+
/**
28+
* Abstract class used for common elements.
29+
*
30+
* @version $Id$
31+
* @since 1.31
32+
*/
33+
public abstract class AbstractLicensorTargetableEvent implements TargetableEvent
34+
{
35+
private Set<String> notifiedGroups = new HashSet<>();
36+
37+
@Override
38+
public Set<String> getTarget()
39+
{
40+
return notifiedGroups;
41+
}
42+
43+
/**
44+
* Set the groups that should be notified.
45+
*
46+
* @param notifiedGroups the notified groups.
47+
*/
48+
public void setNotifiedGroups(Set<String> notifiedGroups)
49+
{
50+
this.notifiedGroups = notifiedGroups;
51+
}
52+
}

application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/upgrades/NewExtensionVersionAvailableManager.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import java.util.HashMap;
2424
import java.util.List;
2525
import java.util.Map;
26+
import java.util.Set;
2627

2728
import javax.inject.Inject;
29+
import javax.inject.Provider;
2830
import javax.inject.Singleton;
2931

3032
import org.apache.commons.lang3.exception.ExceptionUtils;
@@ -34,10 +36,13 @@
3436
import org.xwiki.extension.InstalledExtension;
3537
import org.xwiki.extension.repository.InstalledExtensionRepository;
3638
import org.xwiki.extension.version.Version;
39+
import org.xwiki.model.reference.DocumentReference;
40+
import org.xwiki.model.reference.EntityReferenceSerializer;
3741
import org.xwiki.observation.ObservationManager;
3842

3943
import com.fasterxml.jackson.core.JsonProcessingException;
4044
import com.fasterxml.jackson.databind.ObjectMapper;
45+
import com.xpn.xwiki.XWikiContext;
4146
import com.xwiki.licensing.LicensedExtensionManager;
4247
import com.xwiki.licensing.LicensingConfiguration;
4348
import com.xwiki.licensing.internal.upgrades.notifications.newVersion.NewExtensionVersionAvailableEvent;
@@ -74,6 +79,12 @@ public class NewExtensionVersionAvailableManager
7479
@Inject
7580
private NewVersionNotificationManager newVersionNotificationManager;
7681

82+
@Inject
83+
private EntityReferenceSerializer<String> serializer;
84+
85+
@Inject
86+
private Provider<XWikiContext> contextProvider;
87+
7788
/**
7889
* Notify the administrators when one of the installed licensed applications has a new version available. Do nothing
7990
* for extensions that have auto upgrades enabled.
@@ -118,9 +129,10 @@ private void notifyExtensionVersionAvailable(ExtensionId extensionId, String nam
118129
extensionInfo.put("extensionName", installedExtension.getName());
119130
extensionInfo.put("namespace", namespaceName);
120131
extensionInfo.put("version", installableVersions.get(0).getValue());
132+
Set<String> notifiedGroups = getTargetGroups();
121133

122134
this.observationManager.notify(new NewExtensionVersionAvailableEvent(
123-
new ExtensionId(extensionId.getId(), installableVersions.get(0)), namespace),
135+
new ExtensionId(extensionId.getId(), installableVersions.get(0)), namespace, notifiedGroups),
124136
extensionId.getId(), (new ObjectMapper()).writeValueAsString(extensionInfo));
125137
this.newVersionNotificationManager.markNotificationAsSent(extensionId.getId(), namespaceName,
126138
installableVersions.get(0).getValue());
@@ -130,4 +142,13 @@ private void notifyExtensionVersionAvailable(ExtensionId extensionId, String nam
130142
extensionId.getId(), ExceptionUtils.getRootCauseMessage(e));
131143
}
132144
}
145+
146+
private Set<String> getTargetGroups()
147+
{
148+
Set<String> notifiedGroups = licensingConfig.getNotifiedGroupsSet();
149+
DocumentReference adminGroupDocument =
150+
new DocumentReference(contextProvider.get().getWikiId(), "XWiki", "XWikiAdminGroup");
151+
notifiedGroups.add(serializer.serialize(adminGroupDocument));
152+
return notifiedGroups;
153+
}
133154
}

application-licensing-licensor/application-licensing-licensor-api/src/main/java/com/xwiki/licensing/internal/upgrades/UpgradeExtensionHandler.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.ArrayList;
2323
import java.util.Collections;
2424
import java.util.List;
25+
import java.util.Set;
2526

2627
import javax.inject.Inject;
2728
import javax.inject.Named;
@@ -46,17 +47,19 @@
4647
import org.xwiki.job.JobException;
4748
import org.xwiki.job.JobExecutor;
4849
import org.xwiki.localization.ContextualLocalizationManager;
50+
import org.xwiki.model.reference.DocumentReference;
4951
import org.xwiki.model.reference.DocumentReferenceResolver;
5052
import org.xwiki.model.reference.EntityReferenceSerializer;
5153
import org.xwiki.observation.ObservationManager;
5254

55+
import com.xwiki.licensing.LicensingConfiguration;
5356
import com.xwiki.licensing.internal.upgrades.notifications.ExtensionAutoUpgradedEvent;
5457
import com.xwiki.licensing.internal.upgrades.notifications.ExtensionAutoUpgradedFailedEvent;
5558

5659
/**
5760
* Upgrades an extension from a namespace to the last compatible version and sends a notification. The notification will
5861
* be displayed only for users that subscribed to it and disabled the System filter since it is send by superadmin user.
59-
*
62+
*
6063
* @version $Id$
6164
* @since 1.17
6265
*/
@@ -95,9 +98,13 @@ public class UpgradeExtensionHandler
9598
@Inject
9699
private EntityReferenceSerializer<String> serializer;
97100

101+
@Inject
102+
private LicensingConfiguration licensingConfig;
103+
104+
98105
/**
99106
* Try upgrading an extension inside a namespace to the last compatible version.
100-
*
107+
*
101108
* @param installedExtension the already installed extension
102109
* @param namespace the namespace in which the extension is installed
103110
*/
@@ -115,8 +122,9 @@ public void tryUpgradeExtensionToLastVersion(InstalledExtension installedExtensi
115122
String doneUpgradeMessage = this.localization.getTranslationPlain(
116123
"licensor.notification.autoUpgrade.done", installedExtension.getName(),
117124
installedExtensionId.getVersion().getValue(), toInstallExtensionId.getVersion().getValue());
118-
119-
this.observationManager.notify(new ExtensionAutoUpgradedEvent(), LICENSOR_API_ID, doneUpgradeMessage);
125+
Set<String> notifiedGroups = getTargetGroups();
126+
this.observationManager.notify(new ExtensionAutoUpgradedEvent(notifiedGroups), LICENSOR_API_ID,
127+
doneUpgradeMessage);
120128

121129
// If the execution gets here, it means that the upgrade was done.
122130
break;
@@ -131,9 +139,18 @@ public void tryUpgradeExtensionToLastVersion(InstalledExtension installedExtensi
131139
}
132140
}
133141

142+
private Set<String> getTargetGroups()
143+
{
144+
Set<String> notifiedGroups = licensingConfig.getNotifiedGroupsSet();
145+
DocumentReference adminGroupDoc = currentDocumentReferenceResolver.resolve("XWiki.XWikiAdminGroup");
146+
String adminGroup = serializer.serialize(adminGroupDoc);
147+
notifiedGroups.add(adminGroup);
148+
return notifiedGroups;
149+
}
150+
134151
/**
135152
* Install the given extension inside a namespace.
136-
*
153+
*
137154
* @param extensionId extension to install
138155
* @param namespace namespace where the install is done
139156
* @throws JobException error at job execution
@@ -183,7 +200,7 @@ protected InstallRequest getInstallRequest(ExtensionId extensionId, String names
183200

184201
/**
185202
* Get the reversed list of versions that can be installed, considering the already installed version.
186-
*
203+
*
187204
* @param extensionId ExtensionId of the application that is needed
188205
* @return reversed list of versions until the already installed one
189206
*/

0 commit comments

Comments
 (0)