diff --git a/portlets/src/main/webapp/WEB-INF/conf/gamification/upgrade-configuration.xml b/portlets/src/main/webapp/WEB-INF/conf/gamification/upgrade-configuration.xml
index dbfddc8dfb..e4ac3e1995 100644
--- a/portlets/src/main/webapp/WEB-INF/conf/gamification/upgrade-configuration.xml
+++ b/portlets/src/main/webapp/WEB-INF/conf/gamification/upgrade-configuration.xml
@@ -76,6 +76,29 @@
+
+ ProgramVisibilityUpgradePlugin
+ addUpgradePlugin
+ io.meeds.gamification.upgrade.ProgramVisibilityUpgradePlugin
+ An upgrade plugin to set a program visibility switch audience registration type
+
+
+ product.group.id
+ The groupId of the product
+ org.exoplatform.social
+
+
+ plugin.execution.order
+ The plugin execution order
+ 5
+
+
+ plugin.upgrade.execute.once
+ Execute only once, not each version change
+ true
+
+
+
diff --git a/portlets/src/main/webapp/WEB-INF/jsp/engagementCenterActions.jsp b/portlets/src/main/webapp/WEB-INF/jsp/engagementCenterActions.jsp
index bcea5e9735..30200b4815 100644
--- a/portlets/src/main/webapp/WEB-INF/jsp/engagementCenterActions.jsp
+++ b/portlets/src/main/webapp/WEB-INF/jsp/engagementCenterActions.jsp
@@ -21,13 +21,12 @@
<%@ page import="io.meeds.gamification.service.ProgramService"%>
<%@ page import="org.exoplatform.container.ExoContainerContext"%>
<%@ page import="io.meeds.gamification.utils.Utils" %>
-<%@ page import="org.exoplatform.services.security.ConversationState" %>
<%
-boolean isAdministrator = Utils.isRewardingManager(ConversationState.getCurrent().getIdentity().getUserId());
-boolean isProgramManager = isAdministrator || ExoContainerContext.getService(ProgramService.class).countOwnedPrograms(ConversationState.getCurrent().getIdentity().getUserId()) > 0;
+ if (Utils.canAccessAnonymousResources()) {
+ boolean isAdministrator = request.getRemoteUser() != null && Utils.isRewardingManager(request.getRemoteUser());
+ boolean isProgramManager = request.getRemoteUser() != null && (isAdministrator || ExoContainerContext.getService(ProgramService.class).countOwnedPrograms(request.getRemoteUser()) > 0);
%>
-
+<% } %>
+
diff --git a/portlets/src/main/webapp/WEB-INF/jsp/programsOverview.jsp b/portlets/src/main/webapp/WEB-INF/jsp/programsOverview.jsp
new file mode 100644
index 0000000000..d883daffda
--- /dev/null
+++ b/portlets/src/main/webapp/WEB-INF/jsp/programsOverview.jsp
@@ -0,0 +1,11 @@
+<%@page import="io.meeds.gamification.utils.Utils"%>
+<% if (Utils.canAccessAnonymousResources()) { %>
+
+<% } %>
+
\ No newline at end of file
diff --git a/portlets/src/main/webapp/WEB-INF/jsp/rulesOverview/index.jsp b/portlets/src/main/webapp/WEB-INF/jsp/rulesOverview.jsp
similarity index 92%
rename from portlets/src/main/webapp/WEB-INF/jsp/rulesOverview/index.jsp
rename to portlets/src/main/webapp/WEB-INF/jsp/rulesOverview.jsp
index e2fc402200..ae70443ac2 100644
--- a/portlets/src/main/webapp/WEB-INF/jsp/rulesOverview/index.jsp
+++ b/portlets/src/main/webapp/WEB-INF/jsp/rulesOverview.jsp
@@ -18,8 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
%>
+<%@page import="io.meeds.gamification.utils.Utils"%>
<%
Object showLocked = request.getAttribute("showLocked");
+ if (Utils.canAccessAnonymousResources()) {
%>
+<% } %>
diff --git a/portlets/src/main/webapp/WEB-INF/jsp/topChallengers.jsp b/portlets/src/main/webapp/WEB-INF/jsp/topChallengers.jsp
new file mode 100644
index 0000000000..85790d2161
--- /dev/null
+++ b/portlets/src/main/webapp/WEB-INF/jsp/topChallengers.jsp
@@ -0,0 +1,10 @@
+<%@page import="io.meeds.gamification.utils.Utils"%>
+<% if (Utils.canAccessAnonymousResources()) { %>
+
+<% } %>
diff --git a/portlets/src/main/webapp/WEB-INF/portlet.xml b/portlets/src/main/webapp/WEB-INF/portlet.xml
index b233fa46da..1ff3f2566c 100644
--- a/portlets/src/main/webapp/WEB-INF/portlet.xml
+++ b/portlets/src/main/webapp/WEB-INF/portlet.xml
@@ -126,7 +126,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
prefetch.resource.rest
-
+
text/html
@@ -258,14 +258,12 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
org.exoplatform.commons.api.portlet.GenericDispatchedViewPortlet
portlet-view-dispatched-file-path
- /html/topChallengers.html
+ /WEB-INF/jsp/topChallengers.jsp
prefetch.resource.rest
- -1
- PUBLIC
text/html
@@ -282,7 +280,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
org.exoplatform.commons.api.portlet.GenericDispatchedViewPortlet
portlet-view-dispatched-file-path
- /WEB-INF/jsp/rulesOverview/index.jsp
+ /WEB-INF/jsp/rulesOverview.jsp
text/html
@@ -306,7 +304,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
org.exoplatform.commons.api.portlet.GenericDispatchedViewPortlet
portlet-view-dispatched-file-path
- /html/programsOverview.html
+ /WEB-INF/jsp/programsOverview.jsp
preload.resource.bundles
@@ -314,10 +312,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
preload.resource.rest
-
+
- -1
- PUBLIC
text/html
diff --git a/portlets/src/main/webapp/html/programsOverview.html b/portlets/src/main/webapp/html/programsOverview.html
deleted file mode 100644
index 9655b9611a..0000000000
--- a/portlets/src/main/webapp/html/programsOverview.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/portlets/src/main/webapp/html/topChallengers.html b/portlets/src/main/webapp/html/topChallengers.html
deleted file mode 100644
index 770e9a3f75..0000000000
--- a/portlets/src/main/webapp/html/topChallengers.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/portlets/src/main/webapp/vue-app/profileStats/components/GamificationRank.vue b/portlets/src/main/webapp/vue-app/profileStats/components/GamificationRank.vue
index 25aabf8402..e5b8a75d14 100644
--- a/portlets/src/main/webapp/vue-app/profileStats/components/GamificationRank.vue
+++ b/portlets/src/main/webapp/vue-app/profileStats/components/GamificationRank.vue
@@ -68,12 +68,14 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
justify-center
align-end>
-
-
-
{{ item.rank }}
-
+ offset-x />
{{ item.score }}
diff --git a/portlets/src/main/webapp/vue-app/usersLeaderboard/components/UsersLeaderboard.vue b/portlets/src/main/webapp/vue-app/usersLeaderboard/components/UsersLeaderboard.vue
index 6792d92baf..3e1b4183ae 100644
--- a/portlets/src/main/webapp/vue-app/usersLeaderboard/components/UsersLeaderboard.vue
+++ b/portlets/src/main/webapp/vue-app/usersLeaderboard/components/UsersLeaderboard.vue
@@ -196,7 +196,7 @@ export default {
});
},
retrievePrograms() {
- return fetch(`${eXo.env.portal.context}/${eXo.env.portal.rest}/gamification/programs?type=ALL&sortByBudget=true`, {
+ return fetch(`${eXo.env.portal.context}/${eXo.env.portal.rest}/gamification/programs?type=ALL`, {
credentials: 'include',
}).then(resp => resp?.ok && resp.json())
.then(data => {
diff --git a/services/src/main/java/io/meeds/gamification/constant/EntityVisibility.java b/services/src/main/java/io/meeds/gamification/constant/EntityVisibility.java
new file mode 100644
index 0000000000..e28b87903f
--- /dev/null
+++ b/services/src/main/java/io/meeds/gamification/constant/EntityVisibility.java
@@ -0,0 +1,26 @@
+/**
+ *
+ * This file is part of the Meeds project (https://meeds.io/).
+ *
+ * Copyright (C) 2023 Meeds Association contact@meeds.io
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+package io.meeds.gamification.constant;
+
+public enum EntityVisibility {
+ RESTRICTED, OPEN;
+}
diff --git a/services/src/main/java/io/meeds/gamification/dao/ProgramDAO.java b/services/src/main/java/io/meeds/gamification/dao/ProgramDAO.java
index 893fddbddf..c7e9bf9ce4 100644
--- a/services/src/main/java/io/meeds/gamification/dao/ProgramDAO.java
+++ b/services/src/main/java/io/meeds/gamification/dao/ProgramDAO.java
@@ -34,6 +34,7 @@
import io.meeds.gamification.constant.EntityFilterType;
import io.meeds.gamification.constant.EntityStatusType;
import io.meeds.gamification.constant.EntityType;
+import io.meeds.gamification.constant.EntityVisibility;
import io.meeds.gamification.entity.ProgramEntity;
import io.meeds.gamification.model.filter.ProgramFilter;
@@ -119,6 +120,9 @@ private void addQueryFilterParameters(ProgramFilter filter, TypedQuery qu
if (CollectionUtils.isNotEmpty(filter.getSpacesIds())) {
query.setParameter("spacesIds", filter.getSpacesIds());
}
+ if (filter.getOwnerId() == 0 && (CollectionUtils.isNotEmpty(filter.getSpacesIds()) || !filter.isAllSpaces())) {
+ query.setParameter("openVisibility", EntityVisibility.OPEN);
+ }
EntityFilterType type = filter.getType();
if (type != null && type != EntityFilterType.ALL) {
query.setParameter("type", EntityType.valueOf(type.name()));
@@ -173,10 +177,10 @@ private void buildPredicates(ProgramFilter filter, List suffixes, List void addQueryFilterParameters(RuleFilter filter, TypedQuery query
if (entityFilterType != null && entityFilterType != EntityFilterType.ALL) {
query.setParameter("filterType", EntityType.valueOf(filter.getType().name()));
}
+ if ((CollectionUtils.isNotEmpty(filter.getSpaceIds()) && !filter.isExcludeNoSpace())
+ || (CollectionUtils.isEmpty(filter.getSpaceIds()) && !filter.isAllSpaces())) {
+ query.setParameter("openVisibility", EntityVisibility.OPEN);
+ }
}
private String getQueryFilterName(String sortField,
@@ -311,11 +316,11 @@ private void buildPredicates(RuleFilter filter, List suffixes, List removePrograms(event));
}
+ @Override
+ public void spaceRegistrationEdited(SpaceLifeCycleEvent event) {
+ CompletableFuture.runAsync(() -> updateProgramsVisibility(event));
+ }
+
+ @ExoTransactional
+ public void updateProgramsVisibility(SpaceLifeCycleEvent event) {
+ String spaceId = event.getSpace().getId();
+ List programIds = getSpaceProgramIds(spaceId);
+ programIds.forEach(programId -> {
+ try {
+ ProgramDTO program = programService.getProgramById(programId);
+ // Force update visibility computing by updating the program
+ programService.updateProgram(program);
+ } catch (Exception e) {
+ LOG.warn("Error updating program with id {} while its space registration with id {} had changed",
+ programId,
+ spaceId,
+ e);
+ }
+ });
+ }
+
@ExoTransactional
public void removePrograms(SpaceLifeCycleEvent event) {
- ProgramFilter spaceProgramsFilter = new ProgramFilter(true);
String spaceId = event.getSpace().getId();
- spaceProgramsFilter.setSpacesIds(Collections.singletonList(Long.parseLong(spaceId)));
- List programIds = programService.getProgramIds(spaceProgramsFilter, 0, -1);
+ List programIds = getSpaceProgramIds(spaceId);
programIds.forEach(programId -> {
try {
ProgramDTO program = programService.getProgramById(programId);
@@ -65,4 +86,10 @@ public void removePrograms(SpaceLifeCycleEvent event) {
});
}
+ private List getSpaceProgramIds(String spaceId) {
+ ProgramFilter spaceProgramsFilter = new ProgramFilter(true);
+ spaceProgramsFilter.setSpacesIds(Collections.singletonList(Long.parseLong(spaceId)));
+ return programService.getProgramIds(spaceProgramsFilter, 0, -1);
+ }
+
}
diff --git a/services/src/main/java/io/meeds/gamification/model/ProgramDTO.java b/services/src/main/java/io/meeds/gamification/model/ProgramDTO.java
index 0b1e449954..3c55f3c712 100644
--- a/services/src/main/java/io/meeds/gamification/model/ProgramDTO.java
+++ b/services/src/main/java/io/meeds/gamification/model/ProgramDTO.java
@@ -20,6 +20,8 @@
import java.util.HashSet;
import java.util.Set;
+import io.meeds.gamification.constant.EntityVisibility;
+
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -29,33 +31,33 @@
@Data
public class ProgramDTO implements Serializable, Cloneable {
- private static final long serialVersionUID = -8857818632949907592L;
+ private static final long serialVersionUID = -8857818632949907592L;
- protected long id;
+ protected long id;
- protected String title;
+ protected String title;
- protected String description;
+ protected String description;
- protected String color;
+ protected String color;
- protected long spaceId;
+ protected long spaceId;
- protected int priority;
+ protected int priority;
- protected String createdBy;
+ protected String createdBy;
- protected String createdDate;
+ protected String createdDate;
- protected String lastModifiedBy;
+ protected String lastModifiedBy;
- protected String lastModifiedDate;
+ protected String lastModifiedDate;
- protected boolean deleted;
+ protected boolean deleted;
- protected boolean enabled;
+ protected boolean enabled;
- protected long budget;
+ protected long budget;
/**
* @deprecated There is no difference anymore between Automatic or Manual
@@ -63,25 +65,27 @@ public class ProgramDTO implements Serializable, Cloneable {
* used
*/
@Deprecated(forRemoval = false, since = "1.5.0")
- protected String type;
+ protected String type;
+
+ protected String coverUploadId;
- protected String coverUploadId;
+ protected String avatarUploadId;
- protected String avatarUploadId;
+ protected long coverFileId;
- protected long coverFileId;
+ protected long avatarFileId;
- protected long avatarFileId;
+ protected String coverUrl;
- protected String coverUrl;
+ protected String avatarUrl;
- protected String avatarUrl;
+ protected Set ownerIds; // NOSONAR
- protected Set ownerIds; // NOSONAR
+ protected long rulesTotalScore;
- protected long rulesTotalScore;
+ protected boolean open;
- protected boolean open;
+ protected EntityVisibility visibility;
/**
* Deprecated should be renamed to spaceId knowing that audienceId should
@@ -131,7 +135,8 @@ public ProgramDTO clone() { // NOSONAR
avatarUrl,
ownerIds == null ? null : new HashSet<>(ownerIds),
rulesTotalScore,
- open);
+ open,
+ visibility);
}
}
diff --git a/services/src/main/java/io/meeds/gamification/model/UserInfoContext.java b/services/src/main/java/io/meeds/gamification/model/UserInfoContext.java
index 76e5c76dd7..eff0b29875 100644
--- a/services/src/main/java/io/meeds/gamification/model/UserInfoContext.java
+++ b/services/src/main/java/io/meeds/gamification/model/UserInfoContext.java
@@ -29,6 +29,8 @@
@ToString(callSuper = true)
public class UserInfoContext extends UserInfo {
+ private boolean canView;
+
private boolean canEdit;
private boolean isAllowedToRealize;
diff --git a/services/src/main/java/io/meeds/gamification/plugin/ProgramTranslationPlugin.java b/services/src/main/java/io/meeds/gamification/plugin/ProgramTranslationPlugin.java
index 8f53124d78..e68f64fb51 100644
--- a/services/src/main/java/io/meeds/gamification/plugin/ProgramTranslationPlugin.java
+++ b/services/src/main/java/io/meeds/gamification/plugin/ProgramTranslationPlugin.java
@@ -58,7 +58,7 @@ public String getObjectType() {
@Override
public boolean hasAccessPermission(long programId, String username) throws ObjectNotFoundException {
- return programService.isProgramMember(programId, username);
+ return programService.canViewProgram(programId, username);
}
@Override
diff --git a/services/src/main/java/io/meeds/gamification/plugin/RuleActivityTypePlugin.java b/services/src/main/java/io/meeds/gamification/plugin/RuleActivityTypePlugin.java
index fad6b15e8e..dc13dba95a 100644
--- a/services/src/main/java/io/meeds/gamification/plugin/RuleActivityTypePlugin.java
+++ b/services/src/main/java/io/meeds/gamification/plugin/RuleActivityTypePlugin.java
@@ -45,7 +45,7 @@ public boolean isActivityViewable(ExoSocialActivity activity, Identity userAclId
if (rule == null) {
throw new UnsupportedOperationException();
} else {
- return programService.isProgramMember(rule.getProgramId(), userAclIdentity.getUserId());
+ return programService.canViewProgram(rule.getProgramId(), userAclIdentity.getUserId());
}
}
diff --git a/services/src/main/java/io/meeds/gamification/plugin/RuleTranslationPlugin.java b/services/src/main/java/io/meeds/gamification/plugin/RuleTranslationPlugin.java
index 88e3090198..045f33a990 100644
--- a/services/src/main/java/io/meeds/gamification/plugin/RuleTranslationPlugin.java
+++ b/services/src/main/java/io/meeds/gamification/plugin/RuleTranslationPlugin.java
@@ -65,7 +65,7 @@ public String getObjectType() {
public boolean hasAccessPermission(long ruleId, String username) throws ObjectNotFoundException {
try {
RuleDTO rule = this.ruleService.findRuleById(ruleId, username);
- return rule != null && programService.isProgramMember(rule.getProgramId(), username);
+ return rule != null && programService.canViewProgram(rule.getProgramId(), username);
} catch (IllegalAccessException e) {
return false;
}
diff --git a/services/src/main/java/io/meeds/gamification/rest/LeaderboardEndpoint.java b/services/src/main/java/io/meeds/gamification/rest/LeaderboardEndpoint.java
index efe4155266..0b26cd5469 100644
--- a/services/src/main/java/io/meeds/gamification/rest/LeaderboardEndpoint.java
+++ b/services/src/main/java/io/meeds/gamification/rest/LeaderboardEndpoint.java
@@ -34,6 +34,7 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang3.StringUtils;
@@ -56,44 +57,50 @@
import io.meeds.gamification.model.StandardLeaderboard;
import io.meeds.gamification.model.filter.LeaderboardFilter;
import io.meeds.gamification.service.RealizationService;
+import io.meeds.gamification.utils.Utils;
+import io.meeds.portal.security.service.SecuritySettingService;
+
import io.swagger.v3.oas.annotations.Parameter;
@Path("/gamification/leaderboard")
@Produces(MediaType.APPLICATION_JSON)
-@RolesAllowed("users")
public class LeaderboardEndpoint implements ResourceContainer {
- private static final Log LOG = ExoLogger.getLogger(LeaderboardEndpoint.class);
+ private static final Log LOG = ExoLogger.getLogger(LeaderboardEndpoint.class);
+
+ private static final String YOUR_CURRENT_RANK_MSG = "Your current rank";
- private static final String YOUR_CURRENT_RANK_MSG = "Your current rank";
+ private static final int DEFAULT_LOAD_CAPACITY = 10;
- private static final int DEFAULT_LOAD_CAPACITY = 10;
+ private static final int MAX_LOAD_CAPACITY = 100;
- private static final int MAX_LOAD_CAPACITY = 100;
+ protected IdentityManager identityManager = null;
- protected IdentityManager identityManager = null;
+ protected RealizationService realizationService = null;
- protected RealizationService realizationService = null;
+ protected RelationshipManager relationshipManager;
- protected RelationshipManager relationshipManager;
+ protected SpaceService spaceService;
- protected SpaceService spaceService;
+ protected SecuritySettingService securitySettingService;
public LeaderboardEndpoint(IdentityManager identityManager,
RealizationService realizationService,
RelationshipManager relationshipManager,
- SpaceService spaceService) {
+ SpaceService spaceService,
+ SecuritySettingService securitySettingService) {
this.identityManager = identityManager;
this.realizationService = realizationService;
this.relationshipManager = relationshipManager;
this.spaceService = spaceService;
+ this.securitySettingService = securitySettingService;
}
@GET
@Path("rank/all")
- @RolesAllowed("users")
- public Response getAllLeadersByRank(@Context
- UriInfo uriInfo,
+ public Response getAllLeadersByRank(
+ @Context
+ UriInfo uriInfo,
@Parameter(description = "Get leaderboard of user or space")
@DefaultValue("user")
@QueryParam("earnerType")
@@ -110,6 +117,9 @@ public Response getAllLeadersByRank(@Context
@DefaultValue("true")
@QueryParam("loadCapacity")
boolean loadCapacity) {
+ if (!Utils.canAccessAnonymousResources(securitySettingService)) {
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
LeaderboardFilter leaderboardFilter = new LeaderboardFilter();
IdentityType identityType = IdentityType.getType(earnerType);
leaderboardFilter.setIdentityType(identityType);
@@ -125,7 +135,8 @@ public Response getAllLeadersByRank(@Context
period = Period.ALL.name();
}
leaderboardFilter.setPeriod(period);
- leaderboardFilter.setCurrentUser(ConversationState.getCurrent().getIdentity().getUserId());
+ String currentUser = Utils.getCurrentUser();
+ leaderboardFilter.setCurrentUser(currentUser);
List leaderboardList = new ArrayList<>();
@@ -135,21 +146,24 @@ public Response getAllLeadersByRank(@Context
return Response.ok(leaderboardList, MediaType.APPLICATION_JSON).build();
}
int index = 1;
+ boolean isAnonymous = StringUtils.isBlank(currentUser);
for (StandardLeaderboard element : standardLeaderboards) {
Identity identity = identityManager.getIdentity(element.getEarnerId());
if (identity == null) {
continue;
}
LeaderboardInfo leaderboardInfo = new LeaderboardInfo();
- leaderboardInfo.setSocialId(identity.getId());
- String technicalId = computeTechnicalId(identity);
- leaderboardInfo.setTechnicalId(technicalId);
- leaderboardInfo.setScore(element.getReputationScore());
- leaderboardInfo.setRemoteId(identity.getRemoteId());
leaderboardInfo.setFullname(identity.getProfile().getFullName());
leaderboardInfo.setAvatarUrl(identity.getProfile().getAvatarUrl());
- leaderboardInfo.setProfileUrl(identity.getProfile().getUrl());
+ leaderboardInfo.setScore(element.getReputationScore());
leaderboardInfo.setRank(index);
+ if (!isAnonymous) {
+ leaderboardInfo.setRemoteId(identity.getRemoteId());
+ leaderboardInfo.setSocialId(identity.getId());
+ String technicalId = computeTechnicalId(identity);
+ leaderboardInfo.setTechnicalId(technicalId);
+ leaderboardInfo.setProfileUrl(identity.getProfile().getUrl());
+ }
leaderboardList.add(leaderboardInfo);
index++;
}
@@ -168,13 +182,15 @@ public Response getAllLeadersByRank(@Context
break;
}
- // Check if the current user is already in top10
- LeaderboardInfo leader = buildCurrentUserRank(date,
- leaderboardFilter.getProgramId(),
- leaderboardList);
- // Complete the final leaderboard
- if (leader != null) {
- leaderboardList.add(leader);
+ if (!isAnonymous) {
+ // Check if the current user is already in top10
+ LeaderboardInfo leader = buildCurrentUserRank(date,
+ leaderboardFilter.getProgramId(),
+ leaderboardList);
+ // Complete the final leaderboard
+ if (leader != null) {
+ leaderboardList.add(leader);
+ }
}
}
return Response.ok(leaderboardList, MediaType.APPLICATION_JSON).build();
diff --git a/services/src/main/java/io/meeds/gamification/rest/ProgramRest.java b/services/src/main/java/io/meeds/gamification/rest/ProgramRest.java
index 85f4df1837..5db2b0c965 100644
--- a/services/src/main/java/io/meeds/gamification/rest/ProgramRest.java
+++ b/services/src/main/java/io/meeds/gamification/rest/ProgramRest.java
@@ -67,6 +67,8 @@
import io.meeds.gamification.rest.model.ProgramRestEntity;
import io.meeds.gamification.service.ProgramService;
import io.meeds.gamification.service.RuleService;
+import io.meeds.gamification.utils.Utils;
+import io.meeds.portal.security.service.SecuritySettingService;
import io.meeds.social.translation.service.TranslationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -100,37 +102,40 @@ public class ProgramRest implements ResourceContainer {
CACHECONTROL.setPrivate(false);
}
- protected PortalContainer portalContainer;
+ protected PortalContainer portalContainer;
- protected ProgramService programService;
+ protected ProgramService programService;
- protected RuleService ruleService;
+ protected RuleService ruleService;
- protected IdentityManager identityManager;
+ protected IdentityManager identityManager;
- protected TranslationService translationService;
+ protected TranslationService translationService;
- public byte[] defaultProgramCover = null; // NOSONAR
+ protected SecuritySettingService securitySettingService;
- public byte[] defaultProgramAvatar = null; // NOSONAR
+ public byte[] defaultProgramCover = null; // NOSONAR
+
+ public byte[] defaultProgramAvatar = null; // NOSONAR
public ProgramRest(PortalContainer portalContainer,
ProgramService programService,
RuleService ruleService,
TranslationService translationService,
- IdentityManager identityManager) {
+ IdentityManager identityManager,
+ SecuritySettingService securitySettingService) {
this.portalContainer = portalContainer;
this.programService = programService;
this.ruleService = ruleService;
this.translationService = translationService;
this.identityManager = identityManager;
+ this.securitySettingService = securitySettingService;
}
@GET
@Produces({
MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN
})
- @RolesAllowed("users")
@Operation(summary = "Retrieves the list of available programs", method = "GET")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Request fulfilled"),
@@ -185,6 +190,9 @@ public Response getPrograms(
@Parameter(description = "Used to retrieve extra information about the program")
@QueryParam("expand")
String expand) {
+ if (!Utils.canAccessAnonymousResources(securitySettingService)) {
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
ProgramFilter programFilter = new ProgramFilter();
programFilter.setSortByBudget(sortByBudget);
@@ -196,7 +204,11 @@ public Response getPrograms(
programFilter.setProgramTitle(query);
}
if (owned) {
- programFilter.setOwnerId(getCurrentUserIdentityId());
+ long currentUserIdentityId = getCurrentUserIdentityId();
+ if (currentUserIdentityId == 0) {
+ return Response.status(Response.Status.UNAUTHORIZED).build();
+ }
+ programFilter.setOwnerId(currentUserIdentityId);
}
List expandFields = getExpandOptions(expand);
@@ -536,7 +548,6 @@ public Response deleteProgramAvatar(
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{programId}")
- @RolesAllowed("users")
@Operation(summary = "Retrieves a program by its technical identifier", method = "GET")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Request fulfilled"),
@@ -559,6 +570,8 @@ public Response getProgramById(
String expand) {
if (programId == 0) {
return Response.status(Response.Status.BAD_REQUEST).entity("Program Id must be not null").build();
+ } else if (!Utils.canAccessAnonymousResources(securitySettingService)) {
+ return Response.status(Status.UNAUTHORIZED).build();
}
String currentUser = getCurrentUser();
try {
diff --git a/services/src/main/java/io/meeds/gamification/rest/RealizationRest.java b/services/src/main/java/io/meeds/gamification/rest/RealizationRest.java
index c7e5f84579..5d48208b98 100644
--- a/services/src/main/java/io/meeds/gamification/rest/RealizationRest.java
+++ b/services/src/main/java/io/meeds/gamification/rest/RealizationRest.java
@@ -143,7 +143,8 @@ public Response getRealizations(
return Response.status(Response.Status.BAD_REQUEST).entity("Either use limit or dates to limit returned results").build();
}
- Identity identity = ConversationState.getCurrent().getIdentity();
+ ConversationState conversationState = ConversationState.getCurrent();
+ Identity identity = conversationState == null ? null : conversationState.getIdentity();
Date fromDate = Utils.parseRFC3339Date(fromDateRfc3339);
Date toDate = Utils.parseRFC3339Date(toDateRfc3339);
diff --git a/services/src/main/java/io/meeds/gamification/rest/RuleRest.java b/services/src/main/java/io/meeds/gamification/rest/RuleRest.java
index 82a729be1c..ec0950a5ca 100644
--- a/services/src/main/java/io/meeds/gamification/rest/RuleRest.java
+++ b/services/src/main/java/io/meeds/gamification/rest/RuleRest.java
@@ -67,6 +67,8 @@
import io.meeds.gamification.service.ProgramService;
import io.meeds.gamification.service.RealizationService;
import io.meeds.gamification.service.RuleService;
+import io.meeds.gamification.utils.Utils;
+import io.meeds.portal.security.service.SecuritySettingService;
import io.meeds.social.translation.service.TranslationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -80,26 +82,29 @@
@Tag(name = "/gamification/rules", description = "Manages rules")
public class RuleRest implements ResourceContainer {
- private final CacheControl cacheControl;
+ private final CacheControl cacheControl;
- protected ProgramService programService;
+ protected ProgramService programService;
- protected RuleService ruleService;
+ protected RuleService ruleService;
- protected RealizationService realizationService;
+ protected RealizationService realizationService;
- protected TranslationService translationService;
+ protected TranslationService translationService;
- protected FavoriteService favoriteService;
+ protected FavoriteService favoriteService;
- protected IdentityManager identityManager;
+ protected IdentityManager identityManager;
+
+ protected SecuritySettingService securitySettingService;
public RuleRest(ProgramService programService,
RuleService ruleService,
RealizationService realizationService,
TranslationService translationService,
FavoriteService favoriteService,
- IdentityManager identityManager) {
+ IdentityManager identityManager,
+ SecuritySettingService securitySettingService) {
cacheControl = new CacheControl();
cacheControl.setNoCache(true);
cacheControl.setNoStore(true);
@@ -109,11 +114,11 @@ public RuleRest(ProgramService programService,
this.translationService = translationService;
this.favoriteService = favoriteService;
this.identityManager = identityManager;
+ this.securitySettingService = securitySettingService;
}
@GET
@Produces(MediaType.APPLICATION_JSON)
- @RolesAllowed("users")
@Operation(summary = "Retrieves the list of available rules", method = "GET")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Request fulfilled"),
@@ -210,6 +215,9 @@ public Response getRules(// NOSONAR
if (limit < 0) {
return Response.status(Response.Status.BAD_REQUEST).entity("Limit must be positive").build();
}
+ if (!Utils.canAccessAnonymousResources(securitySettingService)) {
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
Locale locale = getLocale(lang);
@@ -286,7 +294,6 @@ public Response getRules(// NOSONAR
@GET
@Produces(MediaType.APPLICATION_JSON)
- @RolesAllowed("users")
@Path("{id}")
@Operation(summary = "Retrieves the list of available rules", method = "GET")
@ApiResponses(value = {
@@ -311,6 +318,10 @@ public Response getRule(
@Parameter(description = "Asking for a full representation of a specific subresource, ex: countRealizations", required = false)
@QueryParam("expand")
String expand) {
+ if (!Utils.canAccessAnonymousResources(securitySettingService)) {
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
+
String currentUser = getCurrentUser();
try {
RuleDTO rule = ruleService.findRuleById(id, currentUser);
diff --git a/services/src/main/java/io/meeds/gamification/rest/builder/ProgramBuilder.java b/services/src/main/java/io/meeds/gamification/rest/builder/ProgramBuilder.java
index 1bb33c5cf1..01592348c9 100644
--- a/services/src/main/java/io/meeds/gamification/rest/builder/ProgramBuilder.java
+++ b/services/src/main/java/io/meeds/gamification/rest/builder/ProgramBuilder.java
@@ -101,7 +101,8 @@ public static ProgramRestEntity toRestEntity(ProgramService programService,
program.getSpaceId() > 0 ? Utils.getSpaceById(String.valueOf(program.getSpaceId())) : null,
toUserContext(programService, program, username),
getProgramOwnersByIds(program.getOwnerIds(), program.getSpaceId()),
- activeRulesCount);
+ activeRulesCount,
+ program.getVisibility());
}
public static void translatedLabels(TranslationService translationService, ProgramDTO program, Locale locale) {
@@ -177,29 +178,27 @@ public static UserInfoContext toUserContext(ProgramService programService,
UserInfoContext userContext = new UserInfoContext();
IdentityManager identityManager = CommonsUtils.getService(IdentityManager.class);
- Identity identity = identityManager.getOrCreateUserIdentity(username);
+ Identity identity = StringUtils.isBlank(username) ? null : identityManager.getOrCreateUserIdentity(username);
mapUserInfo(userContext, identity);
if (program != null) {
boolean isOwner = programService.isProgramOwner(program.getId(), username);
+ boolean isMember = programService.isProgramMember(program.getId(), username);
+ boolean canView = programService.canViewProgram(program.getId(), username);
+ boolean canEdit = isOwner && !program.isDeleted();
+ userContext.setManager(isOwner);
+ userContext.setCanEdit(canEdit);
+ userContext.setMember(isMember);
+ userContext.setCanView(canView);
+ userContext.setProgramOwner(isOwner);
+
if (program.isOpen()) {
- boolean isMember = programService.isProgramMember(program.getId(), username);
- userContext.setManager(isOwner);
- userContext.setCanEdit(isOwner);
- userContext.setMember(isMember);
- userContext.setProgramOwner(isOwner);
userContext.setRedactor(true);
} else {
Space space = Utils.getSpaceById(String.valueOf(program.getSpaceId()));
if (space != null) {
- SpaceService spaceService = CommonsUtils.getService(SpaceService.class);
- boolean isSuperManager = spaceService.isSuperManager(username);
- boolean isManager = isSuperManager || spaceService.isManager(space, username);
- boolean isMember = isManager || spaceService.isMember(space, username);
- boolean isRedactor = isManager || spaceService.isRedactor(space, username);
- userContext.setManager(isManager);
- userContext.setMember(isMember);
- userContext.setProgramOwner(isOwner);
- userContext.setCanEdit(isOwner && !program.isDeleted());
+ boolean isRedactor = StringUtils.isNotBlank(username)
+ && CommonsUtils.getService(SpaceService.class)
+ .canRedactOnSpace(space, Utils.getUserAclIdentity(username));
userContext.setRedactor(isRedactor);
}
}
@@ -214,10 +213,12 @@ private static UserInfo toUserInfo(Identity identity) {
}
private static void mapUserInfo(E userInfo, Identity identity) {
- userInfo.setAvatarUrl(identity.getProfile().getAvatarUrl());
- userInfo.setFullName(identity.getProfile().getFullName());
- userInfo.setRemoteId(identity.getRemoteId());
- userInfo.setId(identity.getId());
+ if (identity != null) {
+ userInfo.setAvatarUrl(identity.getProfile().getAvatarUrl());
+ userInfo.setFullName(identity.getProfile().getFullName());
+ userInfo.setRemoteId(identity.getRemoteId());
+ userInfo.setId(identity.getId());
+ }
}
}
diff --git a/services/src/main/java/io/meeds/gamification/rest/model/ProgramRestEntity.java b/services/src/main/java/io/meeds/gamification/rest/model/ProgramRestEntity.java
index 7192aebbb8..c0284d6519 100644
--- a/services/src/main/java/io/meeds/gamification/rest/model/ProgramRestEntity.java
+++ b/services/src/main/java/io/meeds/gamification/rest/model/ProgramRestEntity.java
@@ -22,6 +22,7 @@
import org.exoplatform.social.core.space.model.Space;
+import io.meeds.gamification.constant.EntityVisibility;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.UserInfo;
import lombok.AllArgsConstructor;
@@ -73,7 +74,8 @@ public ProgramRestEntity(long id, // NOSONAR
Space space,
UserInfo userInfo,
List owners,
- int activeRulesCount) {
+ int activeRulesCount,
+ EntityVisibility visibility) {
super(id,
title,
description,
@@ -96,7 +98,8 @@ public ProgramRestEntity(long id, // NOSONAR
avatarUrl,
ownerIds,
rulesTotalScore,
- open);
+ open,
+ visibility);
this.space = space;
this.userInfo = userInfo;
this.owners = owners;
diff --git a/services/src/main/java/io/meeds/gamification/rest/model/ProgramWithRulesRestEntity.java b/services/src/main/java/io/meeds/gamification/rest/model/ProgramWithRulesRestEntity.java
index b9eb061794..468a2d0572 100644
--- a/services/src/main/java/io/meeds/gamification/rest/model/ProgramWithRulesRestEntity.java
+++ b/services/src/main/java/io/meeds/gamification/rest/model/ProgramWithRulesRestEntity.java
@@ -61,7 +61,8 @@ public ProgramWithRulesRestEntity(ProgramDTO program) {
program.getAvatarUrl(),
program.getOwnerIds(),
program.getRulesTotalScore(),
- program.isOpen());
+ program.isOpen(),
+ program.getVisibility());
}
}
diff --git a/services/src/main/java/io/meeds/gamification/service/ProgramService.java b/services/src/main/java/io/meeds/gamification/service/ProgramService.java
index 71e19b4253..89a1a16ca6 100644
--- a/services/src/main/java/io/meeds/gamification/service/ProgramService.java
+++ b/services/src/main/java/io/meeds/gamification/service/ProgramService.java
@@ -40,13 +40,13 @@ public interface ProgramService {
/**
* Gets programs by filter.
*
- * @param programFilter {@link ProgramFilter} used to filter results
- * @param username User name accessing programs
- * @param offset index of the search
- * @param limit limit of results to return
- * @return A {@link List <ProgramDTO>} object
+ * @param programFilter {@link ProgramFilter} used to filter results
+ * @param username User name accessing programs
+ * @param offset index of the search
+ * @param limit limit of results to return
+ * @return A {@link List <ProgramDTO>} object
* @throws IllegalAccessException when user is not authorized to get another
- * owner's programs list
+ * owner's programs list
*/
List getPrograms(ProgramFilter programFilter,
String username,
@@ -56,13 +56,13 @@ List getPrograms(ProgramFilter programFilter,
/**
* Gets Program Ids by filter.
*
- * @param programFilter {@link ProgramFilter} used to filter results
- * @param username User name accessing Programs
- * @param offset index of the search
- * @param limit limit of results to return
- * @return A {@link List <ProgramDTO>} object
+ * @param programFilter {@link ProgramFilter} used to filter results
+ * @param username User name accessing Programs
+ * @param offset index of the search
+ * @param limit limit of results to return
+ * @return A {@link List <ProgramDTO>} object
* @throws IllegalAccessException when user is not authorized to get another
- * owner's Programs list
+ * owner's Programs list
*/
List getProgramIds(ProgramFilter programFilter,
String username,
@@ -72,88 +72,84 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Gets Program Ids by filter.
*
- * @param programFilter {@link ProgramFilter} used to filter results
- * @param offset index of the search
- * @param limit limit of results to return
- * @return A {@link List <ProgramDTO>} object
+ * @param programFilter {@link ProgramFilter} used to filter results
+ * @param offset index of the search
+ * @param limit limit of results to return
+ * @return A {@link List <ProgramDTO>} object
*/
List getProgramIds(ProgramFilter programFilter,
int offset,
int limit);
/**
- * @param username user name
- * @param offset start index for fetch
- * @param limit limit to fetch
- * @return {@link List} of {@link ProgramDTO} id of programs where
- * the user is owner
+ * @param username user name
+ * @param offset start index for fetch
+ * @param limit limit to fetch
+ * @return {@link List} of {@link ProgramDTO} id of programs where the user is
+ * owner
*/
List getOwnedProgramIds(String username, int offset, int limit);
/**
- * @param username user name
- * @param offset start index for fetch
- * @param limit limit to fetch
- * @return {@link List} of {@link ProgramDTO} id of programs where
- * the user is member of
+ * @param username user name
+ * @param offset start index for fetch
+ * @param limit limit to fetch
+ * @return {@link List} of {@link ProgramDTO} id of programs where the user is
+ * member of
*/
List getMemberProgramIds(String username, int offset, int limit);
/**
* Find a Program by title
*
- * @param programTitle : Program title
- * @return found {@link ProgramDTO}
+ * @param programTitle : Program title
+ * @return found {@link ProgramDTO}
*/
ProgramDTO getProgramByTitle(String programTitle);
/**
* Creates a new Program
*
- * @param program : an object of type ProgramDTO
- * @param aclIdentity Security identity of user attempting to
- * create a program
- * @return created {@link ProgramDTO}
+ * @param program : an object of type ProgramDTO
+ * @param aclIdentity Security identity of user attempting to create a program
+ * @return created {@link ProgramDTO}
* @throws IllegalAccessException when user is not authorized to create a
- * Program for the designated owner defined
- * in object
+ * Program for the designated owner defined in object
*/
ProgramDTO createProgram(ProgramDTO program, Identity aclIdentity) throws IllegalAccessException;
/**
* Creates a new Program
*
- * @param program : an object of type ProgramDTO
- * @return created {@link ProgramDTO}
+ * @param program : an object of type ProgramDTO
+ * @return created {@link ProgramDTO}
*/
ProgramDTO createProgram(ProgramDTO program);
/**
* Update an existing Program
*
- * @param program : an instance of type ProgramDTO
- * @param aclIdentity Security identity of user attempting to
- * update a program
- * @return updated object {@link ProgramDTO}
+ * @param program : an instance of type ProgramDTO
+ * @param aclIdentity Security identity of user attempting to update a program
+ * @return updated object {@link ProgramDTO}
* @throws IllegalArgumentException when user is not authorized to update the
- * Program
- * @throws ObjectNotFoundException when the Program identified by its
- * technical identifier is not found
- * @throws IllegalAccessException when user is not authorized to create a
- * Program for the designated owner defined
- * in object
+ * Program
+ * @throws ObjectNotFoundException when the Program identified by its
+ * technical identifier is not found
+ * @throws IllegalAccessException when user is not authorized to create a
+ * Program for the designated owner defined in object
*/
ProgramDTO updateProgram(ProgramDTO program, Identity aclIdentity) throws ObjectNotFoundException, IllegalAccessException;
/**
* Update an existing Program
*
- * @param program : an instance of type ProgramDTO
- * @return updated object {@link ProgramDTO}
+ * @param program : an instance of type ProgramDTO
+ * @return updated object {@link ProgramDTO}
* @throws IllegalArgumentException when user is not authorized to update the
- * Program
- * @throws ObjectNotFoundException when the Program identified by its
- * technical identifier is not found
+ * Program
+ * @throws ObjectNotFoundException when the Program identified by its
+ * technical identifier is not found
*/
ProgramDTO updateProgram(ProgramDTO program) throws ObjectNotFoundException;
@@ -162,12 +158,11 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Deletes an existing Program by id
*
- * @param programId Program technical identifier to delete
- * @param aclIdentity Security identity of user attempting to
- * delete a program
- * @return deleted {@link ProgramDTO}
- * @throws IllegalAccessException when user is not authorized to delete
- * program
+ * @param programId Program technical identifier to delete
+ * @param aclIdentity Security identity of user attempting to delete a program
+ * @return deleted {@link ProgramDTO}
+ * @throws IllegalAccessException when user is not authorized to delete
+ * program
* @throws ObjectNotFoundException program not found
*/
ProgramDTO deleteProgramById(long programId, Identity aclIdentity) throws ObjectNotFoundException, IllegalAccessException; // NOSONAR
@@ -175,11 +170,11 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Delete program Cover identified by program id
*
- * @param programId {@link ProgramDTO} technical identifier
- * @param aclIdentity Security identity of user attempting to
- * delete the program cover
- * @throws IllegalAccessException when user is not authorized to delete
- * program cover
+ * @param programId {@link ProgramDTO} technical identifier
+ * @param aclIdentity Security identity of user attempting to delete the
+ * program cover
+ * @throws IllegalAccessException when user is not authorized to delete
+ * program cover
* @throws ObjectNotFoundException program not found
*/
void deleteProgramCoverById(long programId, Identity aclIdentity) throws ObjectNotFoundException, IllegalAccessException; // NOSONAR
@@ -187,11 +182,11 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Delete program Avatar identified by program id
*
- * @param programId {@link ProgramDTO} technical identifier
- * @param aclIdentity Security identity of user attempting to
- * delete the program avatar
- * @throws IllegalAccessException when user is not authorized to delete
- * program avatar
+ * @param programId {@link ProgramDTO} technical identifier
+ * @param aclIdentity Security identity of user attempting to delete the
+ * program avatar
+ * @throws IllegalAccessException when user is not authorized to delete
+ * program avatar
* @throws ObjectNotFoundException program not found
*/
void deleteProgramAvatarById(long programId, Identity aclIdentity) throws ObjectNotFoundException, IllegalAccessException;
@@ -199,8 +194,8 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Retrieves a program identified by its technical identifier.
*
- * @param programId : program id
- * @return found {@link ProgramDTO}
+ * @param programId : program id
+ * @return found {@link ProgramDTO}
*/
ProgramDTO getProgramById(long programId);
@@ -208,11 +203,11 @@ List getProgramIds(ProgramFilter programFilter,
* Retrieves a program identified by its technical identifier accessed by a
* user
*
- * @param programId
- * @param username
- * @return found {@link ProgramDTO}
- * @throws IllegalAccessException when user is not authorized to access
- * program
+ * @param programId
+ * @param username
+ * @return found {@link ProgramDTO}
+ * @throws IllegalAccessException when user is not authorized to access
+ * program
* @throws ObjectNotFoundException program not found
*/
ProgramDTO getProgramById(long programId, String username) throws IllegalAccessException, ObjectNotFoundException;
@@ -220,63 +215,59 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Count all Programs by filter
*
- * @param programFilter {@link ProgramFilter} used to filter
- * Programs
- * @param username User name accessing Programs
- * @return Programs count
+ * @param programFilter {@link ProgramFilter} used to filter Programs
+ * @param username User name accessing Programs
+ * @return Programs count
* @throws IllegalAccessException when user is not authorized to get another
- * owner's Programs list
+ * owner's Programs list
*/
int countPrograms(ProgramFilter programFilter, String username) throws IllegalAccessException;
/**
* Count all Programs by filter
*
- * @param programFilter {@link ProgramFilter} used to filter Programs
- * @return Programs count
+ * @param programFilter {@link ProgramFilter} used to filter Programs
+ * @return Programs count
*/
int countPrograms(ProgramFilter programFilter);
/**
- * @param username User name accessing Programs
- * @return Owned Programs count for a given user identified by its
- * name
+ * @param username User name accessing Programs
+ * @return Owned Programs count for a given user identified by its name
*/
int countOwnedPrograms(String username);
/**
- * @param username User name accessing Programs
- * @return Programs as member count for a given user identified by
- * its name
+ * @param username User name accessing Programs
+ * @return Programs as member count for a given user identified by its name
*/
int countMemberPrograms(String username);
/**
* Retrieves the program cover identified by Program technical identifier.
*
- * @param programId Program unique identifier
- * @return found {@link InputStream}
+ * @param programId Program unique identifier
+ * @return found {@link InputStream}
* @throws ObjectNotFoundException When program not found or file attachment
- * not found
+ * not found
*/
InputStream getProgramCoverStream(long programId) throws ObjectNotFoundException;
/**
* Retrieves the program avatar identified by Program technical identifier.
*
- * @param programId Program unique identifier
- * @return found {@link InputStream}
+ * @param programId Program unique identifier
+ * @return found {@link InputStream}
* @throws ObjectNotFoundException When program not found or file attachment
- * not found
+ * not found
*/
InputStream getProgramAvatarStream(long programId) throws ObjectNotFoundException;
/**
* Check whether user can add programs or not
*
- * @param aclIdentity Security identity of user
- * @return true if user has enough privileges to create a program,
- * else false
+ * @param aclIdentity Security identity of user
+ * @return true if user has enough privileges to create a program, else false
*/
boolean canAddProgram(Identity aclIdentity);
@@ -292,21 +283,28 @@ List getProgramIds(ProgramFilter programFilter,
/**
* Check whether user can add programs or not
*
- * @param programId technical identifier of program
- * @param username user name
- * @return true if user has enough privileges to create a program,
- * else false
+ * @param programId technical identifier of program
+ * @param username user name
+ * @return true if user has enough privileges to create a program, else false
*/
boolean isProgramOwner(long programId, String username);
/**
* Check whether user is member of program or not
*
- * @param programId technical identifier of program
- * @param username user name
- * @return true if user has enough privileges to see a program, else
- * false
+ * @param programId technical identifier of program
+ * @param username user name
+ * @return true if user has enough privileges to see a program, else false
*/
boolean isProgramMember(long programId, String username);
+ /**
+ * Check whether user can view program details or not
+ *
+ * @param programId technical identifier of program
+ * @param username user name
+ * @return true if user has enough privileges to see a program, else false
+ */
+ boolean canViewProgram(long programId, String username);
+
}
diff --git a/services/src/main/java/io/meeds/gamification/service/impl/ProgramServiceImpl.java b/services/src/main/java/io/meeds/gamification/service/impl/ProgramServiceImpl.java
index 3942dce2b9..7f9caa6d12 100644
--- a/services/src/main/java/io/meeds/gamification/service/impl/ProgramServiceImpl.java
+++ b/services/src/main/java/io/meeds/gamification/service/impl/ProgramServiceImpl.java
@@ -36,6 +36,7 @@
import org.exoplatform.social.core.space.spi.SpaceService;
import io.meeds.gamification.constant.EntityType;
+import io.meeds.gamification.constant.EntityVisibility;
import io.meeds.gamification.model.ProgramColorAlreadyExists;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.filter.ProgramFilter;
@@ -48,6 +49,8 @@ public class ProgramServiceImpl implements ProgramService {
private static final Log LOG = ExoLogger.getLogger(ProgramServiceImpl.class);
+ private static final String PROGRAM_DOESN_T_EXIST = "Program doesn't exist";
+
protected final ProgramStorage programStorage;
protected final ListenerService listenerService;
@@ -97,6 +100,9 @@ public List getProgramIds(ProgramFilter programFilter,
@Override
public List getOwnedProgramIds(String username, int offset, int limit) {
+ if (StringUtils.isBlank(username)) {
+ return Collections.emptyList();
+ }
org.exoplatform.social.core.identity.model.Identity userIdentity = identityManager.getOrCreateUserIdentity(username);
long userIdentityId = Long.parseLong(userIdentity.getId());
ProgramFilter programFilter = computeOwnedProgramsFilter(userIdentity.getRemoteId(), userIdentityId);
@@ -105,6 +111,9 @@ public List getOwnedProgramIds(String username, int offset, int limit) {
@Override
public List getMemberProgramIds(String username, int offset, int limit) {
+ if (StringUtils.isBlank(username)) {
+ return Collections.emptyList();
+ }
ProgramFilter programFilter = computeMemberProgramsFilter(username);
return getProgramIds(programFilter, offset, limit);
}
@@ -130,6 +139,9 @@ public int countPrograms(ProgramFilter programFilter) {
@Override
public int countOwnedPrograms(String username) {
+ if (StringUtils.isBlank(username)) {
+ return 0;
+ }
org.exoplatform.social.core.identity.model.Identity userIdentity = identityManager.getOrCreateUserIdentity(username);
long userIdentityId = Long.parseLong(userIdentity.getId());
ProgramFilter programFilter = computeOwnedProgramsFilter(userIdentity.getRemoteId(), userIdentityId);
@@ -138,6 +150,9 @@ public int countOwnedPrograms(String username) {
@Override
public int countMemberPrograms(String username) {
+ if (StringUtils.isBlank(username)) {
+ return 0;
+ }
ProgramFilter programFilter = computeMemberProgramsFilter(username);
return countPrograms(programFilter);
}
@@ -173,7 +188,7 @@ public ProgramDTO updateProgram(ProgramDTO program, Identity aclIdentity) throws
ObjectNotFoundException {
ProgramDTO storedProgram = programStorage.getProgramById(program.getId());
if (storedProgram == null) {
- throw new ObjectNotFoundException("Program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (storedProgram.isDeleted()) {
throw new ObjectNotFoundException("Program is marked as deleted");
@@ -204,7 +219,7 @@ public ProgramDTO updateProgram(ProgramDTO program, Identity aclIdentity) throws
public ProgramDTO updateProgram(ProgramDTO program) throws ObjectNotFoundException {
ProgramDTO storedProgram = programStorage.getProgramById(program.getId());
if (storedProgram == null) {
- throw new ObjectNotFoundException("Program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (storedProgram.isDeleted()) {
throw new ObjectNotFoundException("Program is marked as deleted");
@@ -225,12 +240,13 @@ public ProgramDTO deleteProgramById(long programId, Identity aclIdentity) throws
ObjectNotFoundException {
ProgramDTO program = programStorage.getProgramById(programId);
if (program == null) {
- throw new ObjectNotFoundException("program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (aclIdentity == null || !isProgramOwner(programId, aclIdentity.getUserId())) {
throw new IllegalAccessException("The user is not authorized to delete the program");
}
program.setDeleted(true);
+ program.setVisibility(EntityVisibility.RESTRICTED);
program = programStorage.saveProgram(program);
broadcast(GAMIFICATION_DOMAIN_DELETE_LISTENER, program, aclIdentity.getUserId());
return program;
@@ -241,7 +257,7 @@ public void deleteProgramCoverById(long programId, Identity aclIdentity) throws
IllegalAccessException {
ProgramDTO program = programStorage.getProgramById(programId);
if (program == null) {
- throw new ObjectNotFoundException("program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (aclIdentity == null || !isProgramOwner(programId, aclIdentity.getUserId())) {
throw new IllegalAccessException("The user is not authorized to delete the program cover");
@@ -261,7 +277,7 @@ public void deleteProgramAvatarById(long programId, Identity aclIdentity) throws
IllegalAccessException {
ProgramDTO program = programStorage.getProgramById(programId);
if (program == null) {
- throw new ObjectNotFoundException("program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (aclIdentity == null || !isProgramOwner(programId, aclIdentity.getUserId())) {
throw new IllegalAccessException("The user is not authorized to delete the program avatar");
@@ -278,18 +294,14 @@ public void deleteProgramAvatarById(long programId, Identity aclIdentity) throws
@Override
public ProgramDTO getProgramById(long programId, String username) throws IllegalAccessException, ObjectNotFoundException {
- if (StringUtils.isBlank(username)) {
- throw new IllegalAccessException("Username is mandatory");
- }
ProgramDTO program = getProgramById(programId);
if (program == null) {
- throw new ObjectNotFoundException("Program doesn't exist");
+ throw new ObjectNotFoundException(PROGRAM_DOESN_T_EXIST);
}
if (program.isDeleted()) {
throw new ObjectNotFoundException("Program has been deleted");
}
- if (!isProgramMember(programId, username)
- || (!program.isEnabled() && !isProgramOwner(program.getId(), username))) {
+ if (!canViewProgram(program, username)) {
throw new IllegalAccessException("Program isn't accessible");
}
return program;
@@ -307,10 +319,10 @@ public ProgramDTO getProgramById(long programId) {
public InputStream getProgramCoverStream(long programId) throws ObjectNotFoundException {
ProgramDTO program = programStorage.getProgramById(programId);
if (program == null) {
- throw new ObjectNotFoundException("program with id " + programId + " doesn't exist");
+ throw new ObjectNotFoundException(String.format("program with id %s doesn't exist", programId));
}
if (program.getCoverFileId() == 0) {
- throw new ObjectNotFoundException("program with id " + programId + " doesn't have a coverId");
+ throw new ObjectNotFoundException(String.format("program with id %s doesn't have a coverId", programId));
}
return programStorage.getImageAsStream(program.getCoverFileId());
}
@@ -374,6 +386,18 @@ public boolean canUseProgramColor(long programId, String color) {
return canUseProgramColor(color, program == null ? null : program.getColor());
}
+ @Override
+ public boolean canViewProgram(long programId, String username) {
+ ProgramDTO program = getProgramById(programId);
+ return canViewProgram(program, username);
+ }
+
+ private boolean canViewProgram(ProgramDTO program, String username) {
+ return program != null
+ && (program.getVisibility() == EntityVisibility.OPEN || isProgramMember(program.getId(), username))
+ && (program.isEnabled() || isProgramOwner(program.getId(), username));
+ }
+
@SuppressWarnings("unchecked")
private ProgramFilter computeUserSpaces(ProgramFilter programFilter, String username) throws IllegalAccessException { // NOSONAR
programFilter = programFilter.clone();
@@ -397,7 +421,7 @@ private ProgramFilter computeUserSpaces(ProgramFilter programFilter, String user
}
programFilter.setSpacesIds(managedSpaceIds);
}
- } else {
+ } else if (StringUtils.isNotBlank(username)) {
List memberSpacesIds = spaceService.getMemberSpacesIds(username, 0, -1).stream().map(Long::parseLong).toList();
if (CollectionUtils.isNotEmpty(programFilter.getSpacesIds())) {
memberSpacesIds = (List) CollectionUtils.intersection(memberSpacesIds, programFilter.getSpacesIds());
@@ -428,6 +452,7 @@ private ProgramDTO createProgram(ProgramDTO program, String username) {
if (program.isOpen()) {
program.setSpaceId(0);
}
+ program.setVisibility(isSpaceOpen(program.getSpaceId()) ? EntityVisibility.OPEN : EntityVisibility.RESTRICTED);
checkProgramColorUnicity(program.getColor(), null);
return programStorage.saveProgram(program);
}
@@ -468,8 +493,11 @@ private boolean isSpaceManager(long spaceId, String username) {
}
return spaceService.isManager(space, username);
}
-
+
private boolean isSpaceMember(long spaceId, String username) {
+ if (StringUtils.isBlank(username)) {
+ return false;
+ }
Space space = spaceService.getSpaceById(String.valueOf(spaceId));
if (space == null) {
return false;
@@ -477,6 +505,11 @@ private boolean isSpaceMember(long spaceId, String username) {
return spaceService.isMember(space, username);
}
+ private boolean isSpaceOpen(long spaceId) {
+ Space space = spaceId > 0 ? spaceService.getSpaceById(String.valueOf(spaceId)) : null;
+ return space == null || Space.OPEN.equals(space.getRegistration());
+ }
+
private ProgramFilter computeOwnedProgramsFilter(String username, long userIdentityId) {
ProgramFilter programFilter = new ProgramFilter();
programFilter.setIncludeDeleted(true);
@@ -512,6 +545,7 @@ private ProgramFilter computeMemberProgramsFilter(String username) {
private ProgramDTO saveProgramAndBroadcast(ProgramDTO program, ProgramDTO storedProgram, String username) {
checkProgramColorUnicity(program.getColor(), storedProgram.getColor());
+ program.setVisibility(isSpaceOpen(program.getSpaceId()) ? EntityVisibility.OPEN : EntityVisibility.RESTRICTED);
program = programStorage.saveProgram(program);
if (storedProgram.isEnabled() && !program.isEnabled()) {
broadcast(GAMIFICATION_DOMAIN_DISABLE_LISTENER, program, username);
diff --git a/services/src/main/java/io/meeds/gamification/service/impl/RealizationServiceImpl.java b/services/src/main/java/io/meeds/gamification/service/impl/RealizationServiceImpl.java
index 0a4dea1ec0..9f178df380 100644
--- a/services/src/main/java/io/meeds/gamification/service/impl/RealizationServiceImpl.java
+++ b/services/src/main/java/io/meeds/gamification/service/impl/RealizationServiceImpl.java
@@ -525,7 +525,7 @@ public RealizationDTO getRealizationById(long realizationId, Identity userAclIde
RealizationDTO realization = realizationStorage.getRealizationById(realizationId);
if (realization == null) {
throw new ObjectNotFoundException(String.format(REALIZATION_NOT_EXIST_MESSAGE, realizationId));
- } else if (programService.isProgramMember(realization.getProgram().getId(), userAclIdentity.getUserId())
+ } else if (programService.canViewProgram(realization.getProgram().getId(), userAclIdentity.getUserId())
|| realization.getEarnerId().equals(userIdentity.getId())) {
return realization;
} else {
@@ -583,7 +583,7 @@ private RealizationFilter computeProgramFilter(RealizationFilter realizationFilt
throw new IllegalArgumentException("filter is mandatory");
}
if (userAclIdentity == null) {
- throw new IllegalArgumentException("identity is mandatory");
+ return null;
}
realizationFilter = realizationFilter.clone();
checkDates(realizationFilter.getFromDate(), realizationFilter.getToDate());
@@ -607,7 +607,7 @@ private RealizationFilter computeProgramFilter(RealizationFilter realizationFilt
realizationFilter.setProgramIds(ownedProgramIds);
}
}
- } else if (isFilterByPrograms && !isProgramsMember(filterProgramIds, userAclIdentity.getUserId())) {
+ } else if (isFilterByPrograms && !canViewPrograms(filterProgramIds, userAclIdentity.getUserId())) {
throw new IllegalAccessException("User is not member of one or several selected programs :" + filterProgramIds);
} else if (!isFilterByPrograms && !isSelfFilter(realizationFilter, username)) {
List memberProgramIds = programService.getMemberProgramIds(userAclIdentity.getUserId(), 0, -1);
@@ -656,9 +656,9 @@ private boolean isProgramsOwner(List programIds, String username) {
.allMatch(programId -> programService.isProgramOwner(programId, username));
}
- private boolean isProgramsMember(List programIds, String username) {
+ private boolean canViewPrograms(List programIds, String username) {
return programIds.stream()
- .allMatch(programId -> programService.isProgramMember(programId, username));
+ .allMatch(programId -> programService.canViewProgram(programId, username));
}
private List filterAuthorizedSpaces(List result,
diff --git a/services/src/main/java/io/meeds/gamification/service/impl/RuleServiceImpl.java b/services/src/main/java/io/meeds/gamification/service/impl/RuleServiceImpl.java
index ebebd5629f..a392818ae3 100644
--- a/services/src/main/java/io/meeds/gamification/service/impl/RuleServiceImpl.java
+++ b/services/src/main/java/io/meeds/gamification/service/impl/RuleServiceImpl.java
@@ -122,9 +122,6 @@ public RuleDTO findRuleById(long ruleId, String username) throws IllegalAccessEx
if (ruleId <= 0) {
throw new IllegalArgumentException("ruleId is mandatory");
}
- if (StringUtils.isBlank(username)) {
- throw new IllegalAccessException(USERNAME_IS_MANDATORY_MESSAGE);
- }
RuleDTO rule = findRuleById(ruleId);
if (rule == null) {
throw new ObjectNotFoundException("Rule doesn't exist");
@@ -135,7 +132,7 @@ public RuleDTO findRuleById(long ruleId, String username) throws IllegalAccessEx
if (!isRuleManager(rule, username)
&& (!rule.isEnabled()
|| rule.getProgram() == null
- || !programService.isProgramMember(rule.getProgram().getId(), username))) {
+ || !programService.canViewProgram(rule.getProgram().getId(), username))) {
throw new IllegalAccessException("Rule isn't accessible");
}
if (rule.getProgram() != null) {
@@ -438,7 +435,7 @@ private RuleDTO createRuleAndBroadcast(RuleDTO rule, String username) {
private boolean isRuleManager(RuleDTO rule, String username) {
ProgramDTO program = rule.getProgram();
- if (program == null) {
+ if (program == null || StringUtils.isBlank(username)) {
return false;
} else {
return programService.isProgramOwner(program.getId(), username);
diff --git a/services/src/main/java/io/meeds/gamification/storage/mapper/ProgramMapper.java b/services/src/main/java/io/meeds/gamification/storage/mapper/ProgramMapper.java
index bd87b8f822..05ee29274d 100644
--- a/services/src/main/java/io/meeds/gamification/storage/mapper/ProgramMapper.java
+++ b/services/src/main/java/io/meeds/gamification/storage/mapper/ProgramMapper.java
@@ -23,6 +23,7 @@
import org.apache.commons.lang3.StringUtils;
import io.meeds.gamification.constant.EntityType;
+import io.meeds.gamification.constant.EntityVisibility;
import io.meeds.gamification.dao.RuleDAO;
import io.meeds.gamification.entity.ProgramEntity;
import io.meeds.gamification.model.ProgramDTO;
@@ -58,8 +59,10 @@ public static ProgramEntity toEntity(ProgramDTO program) {
programEntity.setEnabled(program.isEnabled());
if (program.getSpaceId() > 0 && !program.isOpen()) {
programEntity.setAudienceId(program.getSpaceId());
+ programEntity.setVisibility(program.getVisibility());
} else {
programEntity.setAudienceId(null);
+ programEntity.setVisibility(EntityVisibility.OPEN);
}
if (program.getCreatedDate() != null) {
programEntity.setCreatedDate(Utils.parseRFC3339Date(program.getCreatedDate()));
@@ -119,6 +122,10 @@ public static ProgramDTO fromEntity(RuleDAO ruleDAO, ProgramEntity programEntity
program.setAvatarUrl(avatarUrl);
program.setOwnerIds(programEntity.getOwners());
program.setOpen(programEntity.getAudienceId() == null);
+ program.setVisibility(programEntity.getVisibility());
+ if (program.getVisibility() == null) {
+ program.setVisibility(EntityVisibility.RESTRICTED);
+ }
program.setRulesTotalScore(programEntity.isDeleted() || !programEntity.isEnabled() ? 0
: ruleDAO.getRulesTotalScoreByProgramId(programEntity.getId()));
return program;
diff --git a/services/src/main/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePlugin.java b/services/src/main/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePlugin.java
new file mode 100644
index 0000000000..392a8fc618
--- /dev/null
+++ b/services/src/main/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePlugin.java
@@ -0,0 +1,121 @@
+/**
+ * This file is part of the Meeds project (https://meeds.io/).
+ *
+ * Copyright (C) 2020 - 2023 Meeds Association contact@meeds.io
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package io.meeds.gamification.upgrade;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+
+import org.exoplatform.commons.api.persistence.ExoTransactional;
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.persistence.impl.EntityManagerService;
+import org.exoplatform.commons.upgrade.UpgradeProductPlugin;
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.social.core.space.model.Space;
+import org.exoplatform.social.core.space.spi.SpaceService;
+
+import io.meeds.gamification.constant.EntityVisibility;
+
+public class ProgramVisibilityUpgradePlugin extends UpgradeProductPlugin {
+
+ private static final Log LOG = ExoLogger.getLogger(ProgramVisibilityUpgradePlugin.class);
+
+ private static final String VISIBILITY_PARAM = "visibility";
+
+ private static final String AUDIENCE_IDS_PARAM = "audienceIds";
+
+ private static final String GET_PROGRAM_SPACE_IDS_QUERY =
+ "SELECT DISTINCT p.audienceId FROM GamificationDomain p WHERE p.audienceId > 0";
+
+ private static final String UPGRADE_PROGRAMS_QUERY =
+ "UPDATE GamificationDomain p SET p.visibility = :" + VISIBILITY_PARAM;
+
+ private static final String UPGRADE_PROGRAMS_WITH_AUDIENCE_QUERY =
+ UPGRADE_PROGRAMS_QUERY +
+ " WHERE p.audienceId IS NULL OR p.audienceId = 0 OR p.audienceId IN (:" +
+ AUDIENCE_IDS_PARAM + ")";
+
+ private static final String UPGRADE_PROGRAMS_NO_AUDIENCE_QUERY =
+ "UPDATE GamificationDomain p SET p.visibility = :" +
+ VISIBILITY_PARAM +
+ " WHERE p.audienceId IS NULL OR p.audienceId = 0";
+
+ private EntityManagerService entityManagerService;
+
+ private SpaceService spaceService;
+
+ public ProgramVisibilityUpgradePlugin(EntityManagerService entityManagerService,
+ SpaceService spaceService,
+ SettingService settingService,
+ InitParams initParams) {
+ super(settingService, initParams);
+ this.entityManagerService = entityManagerService;
+ this.spaceService = spaceService;
+ }
+
+ @Override
+ public void processUpgrade(String oldVersion, String newVersion) {
+ LOG.info("Start:: Upgrade Programs Visibility");
+ List spaceIds = getProgramSpaceIds();
+ spaceIds = spaceIds.stream()
+ .map(spaceId -> spaceService.getSpaceById(String.valueOf(spaceId)))
+ .filter(Objects::nonNull)
+ .filter(s -> Space.OPEN.equals(s.getRegistration()))
+ .map(Space::getId)
+ .map(Long::parseLong)
+ .toList();
+ upgradeAllProgramsAsRestricted();
+ int openProgramsCount = upgradeProgramsAsOpen(spaceIds);
+ LOG.info("End:: Upgrade Programs Visibility: {} upgraded as Open.",
+ openProgramsCount);
+ }
+
+ @ExoTransactional
+ public int upgradeAllProgramsAsRestricted() {
+ EntityManager entityManager = entityManagerService.getEntityManager();
+ Query query = entityManager.createQuery(UPGRADE_PROGRAMS_QUERY);
+ query.setParameter(VISIBILITY_PARAM, EntityVisibility.RESTRICTED);
+ return query.executeUpdate();
+ }
+
+ @ExoTransactional
+ public int upgradeProgramsAsOpen(List programSpaceIds) {
+ EntityManager entityManager = entityManagerService.getEntityManager();
+ Query query = entityManager.createQuery(programSpaceIds.isEmpty() ? UPGRADE_PROGRAMS_NO_AUDIENCE_QUERY :
+ UPGRADE_PROGRAMS_WITH_AUDIENCE_QUERY);
+ query.setParameter(VISIBILITY_PARAM, EntityVisibility.OPEN);
+ if (!programSpaceIds.isEmpty()) {
+ query.setParameter(AUDIENCE_IDS_PARAM, programSpaceIds);
+ }
+ return query.executeUpdate();
+ }
+
+ @ExoTransactional
+ public List getProgramSpaceIds() {
+ EntityManager entityManager = entityManagerService.getEntityManager();
+ TypedQuery query = entityManager.createQuery(GET_PROGRAM_SPACE_IDS_QUERY, Long.class);
+ List result = query.getResultList();
+ return result == null ? Collections.emptyList() : result;
+ }
+}
diff --git a/services/src/main/java/io/meeds/gamification/utils/Utils.java b/services/src/main/java/io/meeds/gamification/utils/Utils.java
index 0fbfee8dbf..ea0ff63670 100644
--- a/services/src/main/java/io/meeds/gamification/utils/Utils.java
+++ b/services/src/main/java/io/meeds/gamification/utils/Utils.java
@@ -29,6 +29,7 @@
import org.exoplatform.services.log.Log;
import org.exoplatform.services.security.Authenticator;
import org.exoplatform.services.security.ConversationState;
+import org.exoplatform.services.security.IdentityConstants;
import org.exoplatform.services.security.IdentityRegistry;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.manager.IdentityManager;
@@ -42,6 +43,9 @@
import io.meeds.gamification.model.Announcement;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.RuleDTO;
+import io.meeds.portal.security.constant.UserRegistrationType;
+import io.meeds.portal.security.service.SecuritySettingService;
+
import org.exoplatform.ws.frameworks.json.JsonGenerator;
import org.exoplatform.ws.frameworks.json.impl.*;
@@ -262,14 +266,23 @@ public static long getUserIdentityId(String username) {
Identity identity = identityManager.getOrCreateUserIdentity(username);
return identity == null ? 0l : Long.parseLong(identity.getId());
}
-
+
public static final String getCurrentUser() {
if (ConversationState.getCurrent() != null && ConversationState.getCurrent().getIdentity() != null) {
- return ConversationState.getCurrent().getIdentity().getUserId();
+ String userId = ConversationState.getCurrent().getIdentity().getUserId();
+ return StringUtils.equals(userId, IdentityConstants.ANONIM) ? null : userId;
}
return null;
}
+ public static final boolean canAccessAnonymousResources() {
+ return canAccessAnonymousResources(ExoContainerContext.getService(SecuritySettingService.class));
+ }
+
+ public static final boolean canAccessAnonymousResources(SecuritySettingService securitySettingService) {
+ return StringUtils.isNotBlank(getCurrentUser()) || securitySettingService.getRegistrationType() == UserRegistrationType.OPEN;
+ }
+
public static String toRFC3339Date(Date dateTime) {
if (dateTime == null) {
return null;
@@ -415,6 +428,9 @@ public static boolean isRewardingManager(String username) {
}
public static org.exoplatform.services.security.Identity getUserAclIdentity(String username) {
+ if (StringUtils.isBlank(username)) {
+ return null;
+ }
IdentityRegistry identityRegistry = ExoContainerContext.getService(IdentityRegistry.class);
org.exoplatform.services.security.Identity aclIdentity = identityRegistry.getIdentity(username);
if (aclIdentity == null) {
diff --git a/services/src/main/resources/db/changelog/gamification.db.changelog-1.0.0.xml b/services/src/main/resources/db/changelog/gamification.db.changelog-1.0.0.xml
index 39f7e43ecb..d4b1cd01a2 100644
--- a/services/src/main/resources/db/changelog/gamification.db.changelog-1.0.0.xml
+++ b/services/src/main/resources/db/changelog/gamification.db.changelog-1.0.0.xml
@@ -751,4 +751,18 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+
+
+
+
+
+
+
diff --git a/services/src/test/java/io/meeds/gamification/listener/GamificationSpaceListenerTest.java b/services/src/test/java/io/meeds/gamification/listener/GamificationSpaceListenerTest.java
index 1c3402423b..394c2a385d 100644
--- a/services/src/test/java/io/meeds/gamification/listener/GamificationSpaceListenerTest.java
+++ b/services/src/test/java/io/meeds/gamification/listener/GamificationSpaceListenerTest.java
@@ -30,6 +30,7 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -37,88 +38,108 @@
import java.util.Map;
import java.util.function.BiConsumer;
+import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.MockedStatic;
import org.mockito.junit.MockitoJUnitRunner;
+import org.exoplatform.commons.utils.CommonsUtils;
import org.exoplatform.services.listener.ListenerService;
+import org.exoplatform.services.security.ConversationState;
import org.exoplatform.social.core.identity.model.Identity;
import org.exoplatform.social.core.manager.IdentityManager;
import org.exoplatform.social.core.space.model.Space;
import org.exoplatform.social.core.space.spi.SpaceLifeCycleEvent;
+import org.exoplatform.social.core.space.spi.SpaceLifeCycleListener;
import org.exoplatform.social.core.space.spi.SpaceService;
import io.meeds.gamification.service.RuleService;
@RunWith(MockitoJUnitRunner.Silent.class)
-public class GamificationSpaceListenerTest {
+public class GamificationSpaceListenerTest { // NOSONAR
+
+ private static final MockedStatic COMMONS_UTILS_UTIL = mockStatic(CommonsUtils.class);
@Mock
- private RuleService ruleService;
+ private RuleService ruleService;
@Mock
- private IdentityManager identityManager;
+ private IdentityManager identityManager;
@Mock
- private SpaceService spaceService;
+ private SpaceService spaceService;
@Mock
- private ListenerService listenerService;
+ private ListenerService listenerService;
+
+ @Before
+ public void setUp() {
+ COMMONS_UTILS_UTIL.when(() -> CommonsUtils.getService(IdentityManager.class)).thenReturn(identityManager);
+ ConversationState state = new ConversationState(new org.exoplatform.services.security.Identity("root"));
+ ConversationState.setCurrent(state);
+ }
+
+ @AfterClass
+ public static void tearDown() {
+ COMMONS_UTILS_UTIL.close();
+ }
@Test
public void testSpaceJoin() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_JOIN, (listener, event) -> listener.joined(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_JOIN, SpaceLifeCycleListener::joined);
}
@Test
public void testSpaceLeave() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_JOIN, (listener, event) -> listener.left(event), true);
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_JOIN, SpaceLifeCycleListener::left, true);
}
@Test
public void testAddAppLicationSpace() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_APPLICATIONS, (listener, event) -> listener.applicationAdded(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_APPLICATIONS, SpaceLifeCycleListener::applicationAdded);
}
@Test
public void testRemoveAppLicationSpace() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_APPLICATIONS, (listener, event) -> listener.applicationRemoved(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_APPLICATIONS, SpaceLifeCycleListener::applicationRemoved);
}
@Test
public void testSpaceBannerEdited() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_BANNER, (listener, event) -> listener.spaceBannerEdited(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_BANNER, SpaceLifeCycleListener::spaceBannerEdited);
}
@Test
public void testSpaceAvatarEdited() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_AVATAR, (listener, event) -> listener.spaceAvatarEdited(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_AVATAR, SpaceLifeCycleListener::spaceAvatarEdited);
}
@Test
public void testCreateSpace() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_ADD, (listener, event) -> listener.spaceCreated(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_ADD, SpaceLifeCycleListener::spaceCreated);
}
@Test
public void testUpdateSpaceDescription() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_DESCRIPTION, (listener, event) -> listener.spaceDescriptionEdited(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_UPDATE_DESCRIPTION, SpaceLifeCycleListener::spaceDescriptionEdited);
}
@Test
public void testBecomeSpaceManager() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_GRANT_AS_LEAD, (listener, event) -> listener.grantedLead(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_GRANT_AS_LEAD, SpaceLifeCycleListener::grantedLead);
}
@Test
public void testAddInvitedUser() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_INVITE_USER, (listener, event) -> listener.addInvitedUser(event));
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_INVITE_USER, SpaceLifeCycleListener::addInvitedUser);
}
@Test
public void testRemoveInvitedUser() throws Exception {
- testEventTrigger(GAMIFICATION_SOCIAL_SPACE_INVITE_USER, (listener, event) -> listener.removeInvitedUser(event), true);
+ testEventTrigger(GAMIFICATION_SOCIAL_SPACE_INVITE_USER, SpaceLifeCycleListener::removeInvitedUser, true);
}
private void testEventTrigger(String expectedGamifiedEvent,
diff --git a/services/src/test/java/io/meeds/gamification/mock/SpaceServiceMock.java b/services/src/test/java/io/meeds/gamification/mock/SpaceServiceMock.java
index ffc960940e..ff81168f14 100644
--- a/services/src/test/java/io/meeds/gamification/mock/SpaceServiceMock.java
+++ b/services/src/test/java/io/meeds/gamification/mock/SpaceServiceMock.java
@@ -45,7 +45,9 @@ public class SpaceServiceMock implements SpaceService {
public static final String SPACE_DISPLAY_NAME = "test space";
- public static final String SPACE_ID = "1";
+ public static final String SPACE_ID_1 = "1";
+
+ public static final String SPACE_ID_2 = "200";
public static final List SPACE_MEMBERS = Arrays.asList(new String[] {
"root",
@@ -85,10 +87,10 @@ public Space getSpaceByGroupId(String groupId) {
}
public Space getSpaceById(String spaceId) {
- if (!SPACE_ID.equals(spaceId)) {
+ if (!SPACE_ID_1.equals(spaceId) && !SPACE_ID_2.equals(spaceId)) {
return null;
}
- return getSpace();
+ return getSpace(spaceId);
}
public boolean isRedactor(Space space, String userId) {
@@ -134,7 +136,7 @@ public ListAccess getMemberSpaces(String username) {
public List getMemberSpacesIds(String username, int offset, int limit) {
if (SPACE_MEMBERS.contains(username)) {
- return Collections.singletonList(SPACE_ID);
+ return Collections.singletonList(SPACE_ID_1);
} else {
return Collections.emptyList();
}
@@ -142,7 +144,7 @@ public List getMemberSpacesIds(String username, int offset, int limit) {
public List getManagerSpacesIds(String username, int offset, int limit) {
if (SPACE_MANAGERS.contains(username)) {
- return Collections.singletonList(SPACE_ID);
+ return Collections.singletonList(SPACE_ID_1);
} else {
return Collections.emptyList();
}
@@ -673,8 +675,12 @@ public void removeSuperManagersMembership(String permissionExpression) {
}
private Space getSpace() {
+ return getSpace(SPACE_ID_1);
+ }
+
+ private Space getSpace(String spaceId) {
Space space = new Space();
- space.setId(SPACE_ID);
+ space.setId(spaceId);
space.setPrettyName(SPACE_PRETTY_NAME);
space.setDisplayName(SPACE_DISPLAY_NAME);
space.setGroupId("/spaces/" + SPACE_PRETTY_NAME);
@@ -682,6 +688,7 @@ private Space getSpace() {
"root1",
});
space.setMembers(SPACE_MEMBERS.toArray(new String[0]));
+ space.setRegistration(SPACE_ID_1.equals(spaceId) ? Space.VALIDATION : Space.OPEN);
return space;
}
diff --git a/services/src/test/java/io/meeds/gamification/plugin/RuleActivityTypePluginTest.java b/services/src/test/java/io/meeds/gamification/plugin/RuleActivityTypePluginTest.java
index 8331d4831b..f50072f242 100644
--- a/services/src/test/java/io/meeds/gamification/plugin/RuleActivityTypePluginTest.java
+++ b/services/src/test/java/io/meeds/gamification/plugin/RuleActivityTypePluginTest.java
@@ -116,11 +116,11 @@ public void testActivityTypePlugin() {
activityManager.addActivityTypePlugin(new RuleActivityTypePlugin(programService, ruleService, initParams));
- when(programService.isProgramMember(rule.getProgramId(), owner.getUserId())).thenReturn(true);
+ when(programService.canViewProgram(rule.getProgramId(), owner.getUserId())).thenReturn(true);
assertTrue(activityManager.isActivityViewable(activity, owner));
assertFalse(activityManager.isActivityViewable(activity, viewer));
- when(programService.isProgramMember(rule.getProgramId(), viewer.getUserId())).thenReturn(true);
+ when(programService.canViewProgram(rule.getProgramId(), viewer.getUserId())).thenReturn(true);
assertTrue(activityManager.isActivityViewable(activity, viewer));
}
diff --git a/services/src/test/java/io/meeds/gamification/rest/TestProgramRest.java b/services/src/test/java/io/meeds/gamification/rest/TestProgramRest.java
index 8a2dff5daa..41a7c6debe 100644
--- a/services/src/test/java/io/meeds/gamification/rest/TestProgramRest.java
+++ b/services/src/test/java/io/meeds/gamification/rest/TestProgramRest.java
@@ -27,10 +27,15 @@
import org.exoplatform.services.rest.impl.ContainerResponse;
import org.exoplatform.services.security.ConversationState;
+import io.meeds.gamification.constant.EntityFilterType;
+import io.meeds.gamification.constant.EntityStatusType;
import io.meeds.gamification.constant.EntityType;
import io.meeds.gamification.entity.ProgramEntity;
+import io.meeds.gamification.mock.SpaceServiceMock;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.UserInfoContext;
+import io.meeds.gamification.model.filter.ProgramFilter;
+import io.meeds.gamification.rest.model.ProgramList;
import io.meeds.gamification.rest.model.ProgramRestEntity;
import io.meeds.gamification.test.AbstractServiceTest;
import io.meeds.gamification.utils.Utils;
@@ -173,8 +178,8 @@ public void testGetProgramCoverById() throws Exception {
StandardCharsets.UTF_8);
ContainerResponse response = getResponse("GET",
- getURLResource("programs/" + Utils.DEFAULT_COVER_REMOTE_ID + "/cover?lastModified="
- + lastUpdateCoverTime + "&r=" + token),
+ getURLResource("programs/" + Utils.DEFAULT_COVER_REMOTE_ID + "/cover?lastModified=" +
+ lastUpdateCoverTime + "&r=" + token),
null);
assertNotNull(response);
assertEquals(200, response.getStatus());
@@ -184,17 +189,15 @@ public void testGetProgramCoverById() throws Exception {
assertEquals(404, response.getStatus());
response = getResponse("GET",
- getURLResource("programs/" + manualDomain.getId() + "/cover?lastModified=" + lastUpdateCoverTime
- + "&r="
- + token),
+ getURLResource("programs/" + manualDomain.getId() + "/cover?lastModified=" + lastUpdateCoverTime +
+ "&r=" + token),
null);
assertNotNull(response);
assertEquals(200, response.getStatus());
response = getResponse("GET",
- getURLResource("programs/" + manualDomain.getId() + "/cover?lastModified=" + lastUpdateCoverTime
- + "&r="
- + "wrongToken"),
+ getURLResource("programs/" + manualDomain.getId() + "/cover?lastModified=" + lastUpdateCoverTime +
+ "&r=" + "wrongToken"),
null);
assertNotNull(response);
assertEquals(403, response.getStatus());
@@ -209,8 +212,8 @@ public void testGetProgramAvatarById() throws Exception {
StandardCharsets.UTF_8);
ContainerResponse response = getResponse("GET",
- getURLResource("programs/" + Utils.DEFAULT_AVATAR_REMOTE_ID + "/avatar?lastModified="
- + lastUpdateAvatarTime + "&r=" + token),
+ getURLResource("programs/" + Utils.DEFAULT_AVATAR_REMOTE_ID +
+ "/avatar?lastModified=" + lastUpdateAvatarTime + "&r=" + token),
null);
assertNotNull(response);
assertEquals(200, response.getStatus());
@@ -221,17 +224,15 @@ public void testGetProgramAvatarById() throws Exception {
assertEquals(404, response.getStatus());
response = getResponse("GET",
- getURLResource("programs/" + manualDomain.getId() + "/avatar?lastModified=" + lastUpdateAvatarTime
- + "&r="
- + token),
+ getURLResource("programs/" + manualDomain.getId() + "/avatar?lastModified=" + lastUpdateAvatarTime +
+ "&r=" + token),
null);
assertNotNull(response);
assertEquals(200, response.getStatus());
response = getResponse("GET",
- getURLResource("programs/" + manualDomain.getId() + "/avatar?lastModified=" + lastUpdateAvatarTime
- + "&r="
- + "wrongToken"),
+ getURLResource("programs/" + manualDomain.getId() + "/avatar?lastModified=" + lastUpdateAvatarTime +
+ "&r=" + "wrongToken"),
null);
assertNotNull(response);
assertEquals(403, response.getStatus());
@@ -305,4 +306,77 @@ public void testGetOpenProgramById() throws Exception {
assertTrue(((UserInfoContext) savedProgram.getUserInfo()).isMember());
assertTrue(((UserInfoContext) savedProgram.getUserInfo()).isProgramOwner());
}
+
+ @Test
+ public void testGetAccessibleProgramById() throws Exception {
+ ProgramFilter filter = new ProgramFilter();
+ filter.setType(EntityFilterType.ALL);
+ filter.setStatus(EntityStatusType.ENABLED);
+ assertEquals(0, programService.getPrograms(filter, null, offset, 10).size());
+ assertEquals(0, programService.countPrograms(filter, null));
+
+ ProgramEntity programEntity = newDomain(EntityType.AUTOMATIC, "testGetAccessibleProgramById", true, Collections.emptySet());
+ ContainerResponse response = getResponse("GET", getURLResource("programs/" + programEntity.getId()), null);
+ assertNotNull(response);
+ assertEquals(401, response.getStatus());
+
+ ProgramDTO program = programService.getProgramById(programEntity.getId());
+ program.setSpaceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ programService.updateProgram(program);
+
+ response = getResponse("GET", getURLResource("programs/" + programEntity.getId()), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ ProgramRestEntity programRestEntity = (ProgramRestEntity) response.getEntity();
+ assertNotNull(programRestEntity);
+ assertEquals(programEntity.getId().longValue(), programRestEntity.getId());
+ assertTrue(((UserInfoContext) programRestEntity.getUserInfo()).isCanView());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isCanEdit());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isManager());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isMember());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isProgramOwner());
+ }
+
+ @Test
+ public void testGetAccessiblePrograms() throws Exception {
+ ProgramFilter filter = new ProgramFilter();
+ filter.setType(EntityFilterType.ALL);
+ filter.setStatus(EntityStatusType.ENABLED);
+ assertEquals(0, programService.getPrograms(filter, null, offset, 10).size());
+ assertEquals(0, programService.countPrograms(filter, null));
+
+ ProgramEntity programEntity = newDomain(EntityType.AUTOMATIC, "testGetAccessiblePrograms", true, Collections.emptySet());
+ ContainerResponse response = getResponse("GET", getURLResource("programs?offset=0&limit=10&returnSize=true"), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+
+ ProgramList programList = (ProgramList) response.getEntity();
+ assertNotNull(programList);
+ assertEquals(0, programList.getSize());
+ assertEquals(0, programList.getPrograms().size());
+
+ ProgramDTO program = programService.getProgramById(programEntity.getId());
+ program.setSpaceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ programService.updateProgram(program);
+
+ response = getResponse("GET", getURLResource("programs?offset=0&limit=10&returnSize=true"), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+
+ programList = (ProgramList) response.getEntity();
+ assertNotNull(programList);
+ assertNotNull(programList.getPrograms());
+ assertEquals(1, programList.getPrograms().size());
+ assertEquals(1, programList.getSize());
+
+ ProgramRestEntity programRestEntity = programList.getPrograms().get(0);
+ assertNotNull(programRestEntity);
+ assertEquals(programEntity.getId().longValue(), programRestEntity.getId());
+ assertTrue(((UserInfoContext) programRestEntity.getUserInfo()).isCanView());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isCanEdit());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isManager());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isMember());
+ assertFalse(((UserInfoContext) programRestEntity.getUserInfo()).isProgramOwner());
+ }
+
}
diff --git a/services/src/test/java/io/meeds/gamification/rest/TestRealizationRest.java b/services/src/test/java/io/meeds/gamification/rest/TestRealizationRest.java
index fc743f5e5c..37092e482a 100644
--- a/services/src/test/java/io/meeds/gamification/rest/TestRealizationRest.java
+++ b/services/src/test/java/io/meeds/gamification/rest/TestRealizationRest.java
@@ -212,6 +212,14 @@ public void testGetAllRealizationsSortByDateAscending() throws Exception {
List realizations = realizationList.getRealizations();
assertEquals(0, realizations.size());
+ startSessionAs("root1");
+ response = getResponse("GET", getURLResource(restPath), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ realizationList = (RealizationList) response.getEntity();
+ realizations = realizationList.getRealizations();
+ assertEquals(0, realizations.size());
+
// add new realization
List createdActionHistories = new ArrayList<>();
ProgramEntity domainEntity = newDomain();
diff --git a/services/src/test/java/io/meeds/gamification/rest/TestRuleRest.java b/services/src/test/java/io/meeds/gamification/rest/TestRuleRest.java
index 990974ec1d..d43328378b 100644
--- a/services/src/test/java/io/meeds/gamification/rest/TestRuleRest.java
+++ b/services/src/test/java/io/meeds/gamification/rest/TestRuleRest.java
@@ -32,8 +32,11 @@
import io.meeds.gamification.constant.EntityType;
import io.meeds.gamification.entity.ProgramEntity;
import io.meeds.gamification.entity.RuleEntity;
+import io.meeds.gamification.mock.SpaceServiceMock;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.RuleDTO;
+import io.meeds.gamification.model.UserInfo;
+import io.meeds.gamification.model.UserInfoContext;
import io.meeds.gamification.rest.model.ProgramWithRulesRestEntity;
import io.meeds.gamification.rest.model.RuleList;
import io.meeds.gamification.rest.model.RuleRestEntity;
@@ -263,7 +266,7 @@ public void testUpdateRule() throws Exception {
assertNotNull(response);
assertEquals(404, response.getStatus());
}
-
+
@Test
public void testGetRuleById() throws Exception {
startSessionAs("root1");
@@ -271,40 +274,40 @@ public void testGetRuleById() throws Exception {
StringWriter writer = new StringWriter();
JSONWriter jsonWriter = new JSONWriter(writer);
jsonWriter.object()
- .key("title")
- .value("Rule")
- .key("description")
- .value("Rule description")
- .key("startDate")
- .value(START_DATE)
- .key("endDate")
- .value(END_DATE)
- .key("points")
- .value("10")
- .key("program")
- .object()
- .key("id")
- .value(domain.getId())
- .endObject()
- .endObject();
-
+ .key("title")
+ .value("Rule")
+ .key("description")
+ .value("Rule description")
+ .key("startDate")
+ .value(START_DATE)
+ .key("endDate")
+ .value(END_DATE)
+ .key("points")
+ .value("10")
+ .key("program")
+ .object()
+ .key("id")
+ .value(domain.getId())
+ .endObject()
+ .endObject();
+
ContainerResponse response = getResponse("POST", getURLResource("rules"), writer.getBuffer().toString());
assertNotNull(response);
assertEquals(200, response.getStatus());
RuleRestEntity ruleRestEntity = (RuleRestEntity) response.getEntity();
assertNotNull(ruleRestEntity);
startSessionAs("root2");
-
+
response = getResponse("GET", getURLResource("rules/0"), null);
assertNotNull(response);
assertEquals(400, response.getStatus());
-
+
response = getResponse("GET", getURLResource("rules/555"), null);
assertNotNull(response);
assertEquals(404, response.getStatus());
-
+
startSessionAs("root1");
-
+
response = getResponse("GET", getURLResource("rules/" + ruleRestEntity.getId()), null);
assertNotNull(response);
assertEquals(200, response.getStatus());
@@ -313,43 +316,43 @@ public void testGetRuleById() throws Exception {
assertEquals(ruleRestEntity.getId(), savedRuleRestEntity.getId());
assertFalse(savedRuleRestEntity.isPublished());
}
-
+
@Test
public void testGetRules() throws Exception {
ProgramEntity domainEntity = newDomain();
-
+
newRule("rule", domainEntity.getId());
newRule("rule1", domainEntity.getId());
-
+
startSessionAs("root0");
ContainerResponse response = getResponse("GET", getURLResource("rules?returnSize=true"), null);
assertEquals(200, response.getStatus());
-
+
response = getResponse("GET", getURLResource("rules?returnSize=true&limit=-1"), null);
assertEquals(400, response.getStatus());
-
+
response = getResponse("GET", getURLResource("rules?returnSize=true&offset=-1"), null);
assertEquals(400, response.getStatus());
-
+
response = getResponse("GET", getURLResource("rules?returnSize=true&programId=" + domainEntity.getId()), null);
assertEquals(200, response.getStatus());
RuleList rules = (RuleList) response.getEntity();
assertNotNull(rules);
assertEquals(0, rules.getSize());
-
+
startSessionAsAdministrator("root1");
response = getResponse("GET", getURLResource("rules?returnSize=true&programId=" + domainEntity.getId()), null);
assertEquals(200, response.getStatus());
rules = (RuleList) response.getEntity();
assertNotNull(rules);
assertEquals(2, rules.getSize());
-
+
response = getResponse("GET", getURLResource("rules?returnSize=true&spaceId=5555"), null);
assertEquals(200, response.getStatus());
rules = (RuleList) response.getEntity();
assertNotNull(rules);
assertEquals(0, rules.getSize());
-
+
response = getResponse("GET",
getURLResource("rules?returnSize=true&spaceId=" + domainEntity.getAudienceId() + "&spaceId=5555"),
null);
@@ -358,7 +361,7 @@ public void testGetRules() throws Exception {
assertNotNull(rules);
assertEquals(2, rules.getSize());
}
-
+
@Test
public void testGetRulesByUser() throws Exception {
startSessionAs("root1");
@@ -367,27 +370,27 @@ public void testGetRulesByUser() throws Exception {
StringWriter writer = new StringWriter();
JSONWriter jsonWriter = new JSONWriter(writer);
jsonWriter.object()
- .key("title")
- .value("Rule")
- .key("description")
- .value("Rule description")
- .key("startDate")
- .value(START_DATE)
- .key("endDate")
- .value(END_DATE)
- .key("points")
- .value("10")
- .key("enabled")
- .value(true)
- .key("program")
- .object()
- .key("id")
- .value(domain.getId())
- .endObject()
- .endObject();
-
+ .key("title")
+ .value("Rule")
+ .key("description")
+ .value("Rule description")
+ .key("startDate")
+ .value(START_DATE)
+ .key("endDate")
+ .value(END_DATE)
+ .key("points")
+ .value("10")
+ .key("enabled")
+ .value(true)
+ .key("program")
+ .object()
+ .key("id")
+ .value(domain.getId())
+ .endObject()
+ .endObject();
+
ContainerResponse response = getResponse("POST", restPath, writer.getBuffer().toString());
-
+
assertNotNull(response);
assertEquals(200, response.getStatus());
RuleRestEntity rule = (RuleRestEntity) response.getEntity();
@@ -398,23 +401,23 @@ public void testGetRulesByUser() throws Exception {
rule = (RuleRestEntity) response.getEntity();
assertNotNull(rule);
startSessionAs("root2");
-
+
restPath = GAMIFICATION_RULES_REST_PATH + "?offset=0&limit=10";
response = getResponse("GET", restPath, null);
assertNotNull(response);
assertEquals(200, response.getStatus());
RuleList savedRules = (RuleList) response.getEntity();
assertEquals(0, savedRules.getSize());
-
+
startSessionAs("root1");
-
+
restPath = GAMIFICATION_RULES_REST_PATH + "?offset=0&limit=10&programId=" + domain.getId() + "&announcements=4";
response = getResponse("GET", restPath, null);
assertNotNull(response);
assertEquals(200, response.getStatus());
savedRules = (RuleList) response.getEntity();
assertEquals(2, savedRules.getRules().size());
-
+
restPath = GAMIFICATION_RULES_REST_PATH + "?offset=0&limit=10&programId=0&announcements=4&groupByProgram=true";
response = getResponse("GET", restPath, null);
assertNotNull(response);
@@ -422,7 +425,7 @@ public void testGetRulesByUser() throws Exception {
List domainWithRules = (List) response.getEntity();
assertEquals(1, domainWithRules.size());
assertEquals(2, domainWithRules.get(0).getRules().size());
-
+
restPath = GAMIFICATION_RULES_REST_PATH + "?offset=0&limit=1&returnSize=true";
response = getResponse("GET", restPath, null);
assertNotNull(response);
@@ -432,6 +435,83 @@ public void testGetRulesByUser() throws Exception {
assertEquals(1, savedRules.getRules().size());
}
+ @Test
+ public void testGetRuleByAnonym() throws Exception {
+ ProgramDTO program = newProgram();
+ program = programService.createProgram(program);
+
+ RuleEntity rule = newRule("testGetRuleByAnonym", program.getId());
+
+ ContainerResponse response = getResponse("GET", getURLResource("rules/0"), null);
+ assertNotNull(response);
+ assertEquals(400, response.getStatus());
+
+ response = getResponse("GET", getURLResource("rules/555"), null);
+ assertNotNull(response);
+ assertEquals(404, response.getStatus());
+
+ response = getResponse("GET", getURLResource("rules/" + rule.getId()), null);
+ assertNotNull(response);
+ assertEquals(401, response.getStatus());
+
+ program.setSpaceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ programService.updateProgram(program);
+
+ response = getResponse("GET", getURLResource("rules/" + rule.getId()), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ RuleRestEntity ruleRestEntity = (RuleRestEntity) response.getEntity();
+ assertNotNull(ruleRestEntity);
+ assertEquals(rule.getId(), ruleRestEntity.getId());
+ UserInfoContext userInfo = (UserInfoContext) ruleRestEntity.getUserInfo();
+ assertTrue(userInfo.isCanView());
+ assertFalse(userInfo.isCanEdit());
+ assertFalse(userInfo.isManager());
+ assertFalse(userInfo.isMember());
+ assertFalse(userInfo.isProgramOwner());
+ assertFalse(userInfo.isRedactor());
+ }
+
+ @Test
+ public void testGetRulesByAnonym() throws Exception {
+ ProgramDTO program = newProgram();
+ program = programService.createProgram(program);
+
+ RuleEntity rule = newRule("testGetRulesByAnonym", program.getId());
+
+ ContainerResponse response = getResponse("GET", getURLResource("rules?offset=0&limit=10&returnSize=true"), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ RuleList ruleList = (RuleList) response.getEntity();
+ assertNotNull(ruleList);
+ assertEquals(0, ruleList.getSize());
+ assertNotNull(ruleList.getRules());
+ assertEquals(0, ruleList.getRules().size());
+
+ program.setSpaceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ programService.updateProgram(program);
+
+ response = getResponse("GET", getURLResource("rules?offset=0&limit=10&returnSize=true"), null);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ ruleList = (RuleList) response.getEntity();
+ assertNotNull(ruleList);
+ assertEquals(1, ruleList.getSize());
+ assertNotNull(ruleList.getRules());
+ assertEquals(1, ruleList.getRules().size());
+
+ RuleRestEntity ruleRestEntity = ruleList.getRules().get(0);
+ assertNotNull(ruleRestEntity);
+ assertEquals(rule.getId(), ruleRestEntity.getId());
+ UserInfoContext userInfo = (UserInfoContext) ruleRestEntity.getUserInfo();
+ assertTrue(userInfo.isCanView());
+ assertFalse(userInfo.isCanEdit());
+ assertFalse(userInfo.isManager());
+ assertFalse(userInfo.isMember());
+ assertFalse(userInfo.isProgramOwner());
+ assertFalse(userInfo.isRedactor());
+ }
+
@Test
public void testCreateAndDeleteRule() throws Exception {
startSessionAs("root1");
diff --git a/services/src/test/java/io/meeds/gamification/service/ProgramServiceTest.java b/services/src/test/java/io/meeds/gamification/service/ProgramServiceTest.java
index 7f17ecab81..10fec99f35 100644
--- a/services/src/test/java/io/meeds/gamification/service/ProgramServiceTest.java
+++ b/services/src/test/java/io/meeds/gamification/service/ProgramServiceTest.java
@@ -38,6 +38,7 @@
import io.meeds.gamification.constant.EntityStatusType;
import io.meeds.gamification.constant.EntityType;
import io.meeds.gamification.entity.ProgramEntity;
+import io.meeds.gamification.mock.SpaceServiceMock;
import io.meeds.gamification.model.ProgramColorAlreadyExists;
import io.meeds.gamification.model.ProgramDTO;
import io.meeds.gamification.model.RuleDTO;
@@ -214,14 +215,38 @@ public void testGetDomainsByOwner() throws IllegalAccessException {
filter.setType(EntityFilterType.ALL);
filter.setStatus(EntityStatusType.ENABLED);
assertEquals(0, programService.getPrograms(filter, SPACE_MEMBER_USER, offset, 10).size());
- ProgramEntity domainEntity = newDomain(EntityType.AUTOMATIC, "domain10", true, Collections.emptySet());
+ assertEquals(0, programService.countPrograms(filter, SPACE_MEMBER_USER));
+
+ ProgramEntity programEntity = newDomain(EntityType.AUTOMATIC, "domain10", true, Collections.emptySet());
filter.setOwnerId(10);
assertEquals(0, programService.getPrograms(filter, SPACE_MEMBER_USER, offset, 10).size());
+ assertEquals(0, programService.countPrograms(filter, SPACE_MEMBER_USER));
- domainEntity.setOwners(Collections.singleton(10l));
- programDAO.update(domainEntity);
+ programEntity.setOwners(Collections.singleton(10l));
+ programDAO.update(programEntity);
assertEquals(1, programService.getPrograms(filter, SPACE_MEMBER_USER, offset, 10).size());
+ assertEquals(1, programService.countPrograms(filter, SPACE_MEMBER_USER));
+ }
+
+ @Test
+ public void testGetDomainsByAnonym() throws IllegalAccessException, ObjectNotFoundException {
+ ProgramFilter filter = new ProgramFilter();
+ filter.setType(EntityFilterType.ALL);
+ filter.setStatus(EntityStatusType.ENABLED);
+ assertEquals(0, programService.getPrograms(filter, null, offset, 10).size());
+ assertEquals(0, programService.countPrograms(filter, null));
+
+ ProgramEntity programEntity = newDomain(EntityType.AUTOMATIC, "domain10", true, Collections.emptySet());
+ assertEquals(0, programService.getPrograms(filter, null, offset, 10).size());
+ assertEquals(0, programService.countPrograms(filter, null));
+
+ ProgramDTO program = programService.getProgramById(programEntity.getId());
+ program.setSpaceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ programService.updateProgram(program);
+
+ assertEquals(1, programService.getPrograms(filter, null, offset, 10).size());
+ assertEquals(1, programService.countPrograms(filter, null));
}
@Test
diff --git a/services/src/test/java/io/meeds/gamification/service/RealizationServiceMockTest.java b/services/src/test/java/io/meeds/gamification/service/RealizationServiceMockTest.java
index 8d234ef53b..eb00b100ef 100644
--- a/services/src/test/java/io/meeds/gamification/service/RealizationServiceMockTest.java
+++ b/services/src/test/java/io/meeds/gamification/service/RealizationServiceMockTest.java
@@ -157,7 +157,8 @@ public void testGetRealizationsByFilter() throws IllegalAccessException {
when(identityManager.getOrCreateUserIdentity(userAclIdentity.getUserId())).thenReturn(adminIdentity);
assertThrows(IllegalArgumentException.class,
() -> realizationService.getRealizationsByFilter(null, userAclIdentity, offset, limit));
- assertThrows(IllegalArgumentException.class, () -> realizationService.getRealizationsByFilter(filter, null, offset, limit));
+ assertEquals(0, realizationService.getRealizationsByFilter(filter, null, offset, limit).size());
+ assertEquals(0, realizationService.countRealizationsByFilter(filter, userAclIdentity));
// When
filter.setFromDate(fromDate);
@@ -201,7 +202,7 @@ public void testGetRealizationsByFilter() throws IllegalAccessException {
filter.setFromDate(fromDate);
filter.setToDate(toDate);
assertThrows(IllegalArgumentException.class, () -> realizationService.countRealizationsByFilter(null, userAclIdentity));
- assertThrows(IllegalArgumentException.class, () -> realizationService.countRealizationsByFilter(filter, null));
+ assertEquals(0, realizationService.countRealizationsByFilter(filter, null));
// When
filter.setEarnerIds(null);
diff --git a/services/src/test/java/io/meeds/gamification/test/AbstractServiceTest.java b/services/src/test/java/io/meeds/gamification/test/AbstractServiceTest.java
index 784588e821..912c57f0da 100644
--- a/services/src/test/java/io/meeds/gamification/test/AbstractServiceTest.java
+++ b/services/src/test/java/io/meeds/gamification/test/AbstractServiceTest.java
@@ -261,6 +261,7 @@ public void setUp() throws Exception {
resourceBinder.clear();
ApplicationContextImpl.setCurrent(new ApplicationContextImpl(null, null, providerBinder, null));
launcher = new ResourceLauncher(requestHandler);
+ ConversationState.setCurrent(null);
begin();
}
diff --git a/services/src/test/java/io/meeds/gamification/test/InitContainerTestSuite.java b/services/src/test/java/io/meeds/gamification/test/InitContainerTestSuite.java
index e627f87272..191706e24f 100644
--- a/services/src/test/java/io/meeds/gamification/test/InitContainerTestSuite.java
+++ b/services/src/test/java/io/meeds/gamification/test/InitContainerTestSuite.java
@@ -76,6 +76,7 @@
import io.meeds.gamification.storage.ProgramStorageTest;
import io.meeds.gamification.storage.RealizationsStorageTest;
import io.meeds.gamification.storage.RuleStorageTest;
+import io.meeds.gamification.upgrade.ProgramVisibilityUpgradePluginTest;
import io.meeds.gamification.utils.UtilsTest;
@RunWith(Suite.class)
@@ -132,6 +133,7 @@
ActionPublishedNotificationPluginTest.class,
RuleActivityTypePluginTest.class,
EventServiceTest.class,
+ ProgramVisibilityUpgradePluginTest.class,
})
@ConfigTestCase(AbstractServiceTest.class)
public class InitContainerTestSuite extends BaseExoContainerTestSuite {
diff --git a/services/src/test/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePluginTest.java b/services/src/test/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePluginTest.java
new file mode 100644
index 0000000000..b8c4d25b6b
--- /dev/null
+++ b/services/src/test/java/io/meeds/gamification/upgrade/ProgramVisibilityUpgradePluginTest.java
@@ -0,0 +1,71 @@
+/**
+ * This file is part of the Meeds project (https://meeds.io/).
+ *
+ * Copyright (C) 2020 - 2023 Meeds Association contact@meeds.io
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package io.meeds.gamification.upgrade;
+
+import org.exoplatform.commons.api.settings.SettingService;
+import org.exoplatform.commons.persistence.impl.EntityManagerService;
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.container.xml.ValueParam;
+import org.exoplatform.social.core.space.spi.SpaceService;
+
+import io.meeds.gamification.constant.EntityVisibility;
+import io.meeds.gamification.entity.ProgramEntity;
+import io.meeds.gamification.mock.SpaceServiceMock;
+import io.meeds.gamification.test.AbstractServiceTest;
+
+public class ProgramVisibilityUpgradePluginTest extends AbstractServiceTest {// NOSONAR
+
+ public void testProgramUpgrade() {
+
+ InitParams initParams = new InitParams();
+
+ ValueParam valueParam = new ValueParam();
+ valueParam.setName("product.group.id");
+ valueParam.setValue("org.exoplatform.social");
+ initParams.addParam(valueParam);
+
+ valueParam = new ValueParam();
+ valueParam.setName("plugin.execution.order");
+ valueParam.setValue("5");
+ initParams.addParam(valueParam);
+
+ ProgramEntity program1 = newDomain("testProgramUpgrade1");
+ ProgramEntity program2 = newDomain("testProgramUpgrade2");
+ ProgramEntity program3 = newDomain("testProgramUpgrade3");
+ program3.setAudienceId(Long.parseLong(SpaceServiceMock.SPACE_ID_2));
+ program3 = programDAO.update(program3);
+
+ EntityManagerService entityManagerService = getContainer().getComponentInstanceOfType(EntityManagerService.class);
+ SettingService settingService = getContainer().getComponentInstanceOfType(SettingService.class);
+ SpaceService spaceService = getContainer().getComponentInstanceOfType(SpaceService.class);
+ ProgramVisibilityUpgradePlugin upgradePlugin = new ProgramVisibilityUpgradePlugin(entityManagerService,
+ spaceService,
+ settingService,
+ initParams);
+ upgradePlugin.setName("ProgramVisibilityUpgradePlugin");
+ assertTrue(upgradePlugin.isEnabled());
+
+ upgradePlugin.processUpgrade(null, null);
+ restartTransaction();
+
+ assertEquals(EntityVisibility.RESTRICTED, programDAO.find(program1.getId()).getVisibility());
+ assertEquals(EntityVisibility.RESTRICTED, programDAO.find(program2.getId()).getVisibility());
+ assertEquals(EntityVisibility.OPEN, programDAO.find(program3.getId()).getVisibility());
+ }
+
+}