
com.adobe.cq.social.group.api.GroupUtil Maven / Gradle / Ivy
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
package com.adobe.cq.social.group.api;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.Privilege;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.social.community.api.CommunityConstants;
import com.adobe.cq.social.community.api.CommunityContext;
import com.adobe.cq.social.console.utils.api.UserUtils;
import com.adobe.cq.social.group.client.api.CommunityGroup;
import com.adobe.cq.social.group.client.api.CommunityGroupConstants;
import com.adobe.cq.social.scf.OperationException;
import com.adobe.cq.social.site.api.CommunitySiteConstants;
import com.adobe.cq.social.site.api.SiteConfiguration;
import com.adobe.granite.security.user.UserProperties;
import com.adobe.granite.security.user.UserPropertiesManager;
import com.adobe.granite.security.user.UserPropertiesService;
import com.adobe.granite.socialgraph.Direction;
import com.adobe.granite.socialgraph.GraphNode;
import com.adobe.granite.socialgraph.Relationship;
import com.adobe.granite.socialgraph.SocialGraph;
import com.adobe.granite.xss.XSSAPI;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
/**
* GroupUtil
provides various methods managing community groups.
*/
public class GroupUtil {
public static final int DEFAULT_MAX_WAIT_TIME = 2000;
public static final int DEFAULT_WAIT_BETWEEN_RETRIES = 100;
public static final int WARN_WAIT_TIME = 120000;
public static final int WARN_RETRY_DELAY = 1000;
private static final String ANONYMOUS_USER = "anonymous";
private static final Logger log = LoggerFactory.getLogger(GroupUtil.class);
@Reference
private static XSSAPI xssAPI;
public static boolean canEveryoneCreateGroup(final Resource resource) {
// check the group configure first
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final ResourceResolver resolver = resource.getResourceResolver();
final Resource configure = resolver.getResource(context.getSitePath());
if (configure == null) {
return false;
}
final ValueMap values = configure.adaptTo(ValueMap.class);
final String groupCreationType =
values.get(CommunitySiteConstants.PROP_CONFIG_GROUP_CREATION_PERMISSION_TYPE, String.class);
return StringUtils.equalsIgnoreCase(groupCreationType,
SiteConfiguration.GroupManagementConfiguration.CreatePermission.EVERYONE.name());
}
/**
* Validate if a community group name is unique.
* @param resolver resource resolver.
* @param name community group name.
* @param groupRoot community group site path.
* @return true
if a community group name is unique.
*/
public static boolean validateGroupName(final ResourceResolver resolver, final String name, final String groupRoot) {
// group name cannot start with _
if (name.startsWith("_")) {
log.info("Group name {} begins with invalid charactor", name);
return false;
}
// check if a child page with the given name already exists
final PageManager pm = resolver.adaptTo(PageManager.class);
final Page childPage = pm.getPage(groupRoot + "/" + name);
if (childPage != null) {
log.info("Page {} already exists in {}", name, groupRoot);
return false;
}
// check if a member group with the given name already exists
final CommunityContext site = resolver.getResource(groupRoot).adaptTo(CommunityContext.class);
String memberGroup = name + GroupConstants.GROUP_MEMBERGROUP_SUFFIX;
if (site != null) {
memberGroup = site.getTenantUserGroupName(site.getSiteId() + CommunityConstants.DASH_CHAR + memberGroup);
}
try {
final Session session = resolver.adaptTo(Session.class);
final UserManager um = ((JackrabbitSession) session).getUserManager();
final Authorizable group = um.getAuthorizable(memberGroup);
if (group != null) {
log.info("Authorizable {} already exists", memberGroup);
return false;
}
} catch (final RepositoryException e) {
log.error("Failed to validate user group " + memberGroup, e);
return false;
}
return true;
}
/**
* Returns the number of the group members.
* @param userPropertiesService user properties service.
* @param resourceResolver resource resolver.
* @param groupId group id.
* @return Number of the members of this Group. This includes both declared members and all authorizables that are
* indirect group members.
*/
public static int getNumberOfMembers(final UserPropertiesService userPropertiesService,
final ResourceResolver resourceResolver, final String groupId) {
final List relations =
establishMemberRelation(userPropertiesService, resourceResolver, groupId);
if (relations != null) {
return relations.size();
} else {
return 0;
}
}
/**
* Returns true if an authorizable is a group member.
* @param userPropertiesService user properties service.
* @param resourceResolver resource resolver.
* @param authId authorizable id.
* @param groupId group id.
* @return true
if an authorizable is a group member.
*/
public static boolean isMember(final UserPropertiesService userPropertiesService,
final ResourceResolver resourceResolver, final String authId, final String groupId) {
if (StringUtils.isEmpty(authId) || StringUtils.isEmpty(groupId)) {
return false;
}
final SocialGraph socialGraph = resourceResolver.adaptTo(SocialGraph.class);
final GraphNode group = socialGraph.getNode(groupId);
final GraphNode user = socialGraph.getNode(authId);
if (group == null || user == null) {
return false;
}
final String relation = "member";
final Direction direction = Direction.INCOMING;
return (group.getRelationship(direction, user, relation) != null);
}
/**
* Establish Social Graph relations of the group members.
* @param userPropertiesService user properties service.
* @param resourceResolver resource resolver.
* @param groupId group id.
* @return List of UserProperties which are members of this Group. This includes both declared members and all
* authorizables that are indirect group members.
*/
private static List establishMemberRelation(final UserPropertiesService userPropertiesService,
final ResourceResolver resourceResolver, final String groupId) {
final List results = new ArrayList();
if (StringUtils.isEmpty(groupId)) {
return results;
}
try {
final UserPropertiesManager upm = userPropertiesService.createUserPropertiesManager(resourceResolver);
final SocialGraph socialGraph = resourceResolver.adaptTo(SocialGraph.class);
final GraphNode group = socialGraph.getNode(groupId);
if (group == null) {
return results;
}
final String relation = "member";
final Direction direction = Direction.INCOMING;
for (final Relationship r : group.getRelationships(direction, relation)) {
final String authId = r.getOtherNode(group).getId();
// skip groups and other non authorizable relations
final UserProperties memberProperties = upm.getUserProperties(authId, "profile");
if (memberProperties == null || memberProperties.getNode().getPath().contains("groups")) {
continue;
}
results.add(memberProperties);
}
} catch (final RepositoryException e) {
log.error("establishMemberRelation: error while establish relation for [{}]", groupId);
log.error("", e);
}
return results;
}
/**
* wait for page content creation to complete. wait no more than 1 second.
* @param resolver resource resolver.
* @param pagePath page path
* @param maxWaitTime time out in millisecond
* @param waitInterval wait interval in millisecond
*/
public static void waitForPageCreation(final ResourceResolver resolver, final String pagePath, long maxWaitTime,
long waitInterval) throws RepositoryException {
log.debug("Wait for page creation at {}", pagePath);
if (resolver == null || StringUtils.isEmpty(pagePath)) {
return;
}
if (maxWaitTime <= 0) {
log.warn("Invalid maxWaitTime [{}]. Resetting.", maxWaitTime);
maxWaitTime = GroupUtil.DEFAULT_MAX_WAIT_TIME;
}
if (maxWaitTime > GroupUtil.WARN_WAIT_TIME) {
log.warn("Very large number of retries configured [{}]. This may cause thread contention.", maxWaitTime);
}
if (waitInterval <= 0) {
log.warn("Invalid wait interval [{}]. Resetting.", waitInterval);
waitInterval = GroupUtil.DEFAULT_WAIT_BETWEEN_RETRIES;
}
if (waitInterval > GroupUtil.WARN_RETRY_DELAY) {
log.warn("Very large wait interval configured [{}]. This may cause thread contention.", waitInterval);
}
final long start = System.currentTimeMillis();
boolean wait = false;
do {
final Resource res = resolver.resolve(pagePath + "/" + JcrConstants.JCR_CONTENT);
if (res != null && !ResourceUtil.isNonExistingResource(res)) {
if (wait) {
log.debug("Page content successfully created at {} after waiting for {} milliseconds", pagePath,
(System.currentTimeMillis() - start));
} else {
log.debug("Page content successfully created at {} already", pagePath);
}
return;
}
wait = true;
try {
Thread.sleep(waitInterval);
} catch (final InterruptedException ignore) {
}
resolver.adaptTo(Session.class).refresh(true);
resolver.refresh();
} while (System.currentTimeMillis() - start < maxWaitTime);
log.debug("Page content failed to be created at {} ", pagePath);
}
public static Object toObject(final String value, final Class clazz) {
if (Boolean.class == clazz || Boolean.TYPE == clazz) {
return Boolean.valueOf(value);
}
if (Byte.class == clazz || Byte.TYPE == clazz) {
try {
return Long.valueOf(value).byteValue();
} catch (final NumberFormatException e) {
return Double.valueOf(value).byteValue();
}
}
if (Short.class == clazz || Short.TYPE == clazz) {
try {
return Long.valueOf(value).shortValue();
} catch (final NumberFormatException e) {
return Double.valueOf(value).shortValue();
}
}
if (Integer.class == clazz || Integer.TYPE == clazz) {
try {
return Long.valueOf(value).intValue();
} catch (final NumberFormatException e) {
return Double.valueOf(value).intValue();
}
}
if (Long.class == clazz || Long.TYPE == clazz) {
try {
return Long.valueOf(value).longValue();
} catch (final NumberFormatException e) {
return Double.valueOf(value).longValue();
}
}
if (Float.class == clazz || Float.TYPE == clazz) {
try {
return Double.valueOf(value).floatValue();
} catch (final NumberFormatException e) {
return Long.valueOf(value).floatValue();
}
}
if (Double.class == clazz || Double.TYPE == clazz) {
try {
return Double.valueOf(value).doubleValue();
} catch (final NumberFormatException e) {
return Long.valueOf(value).doubleValue();
}
}
return value;
}
/**
* Check if the specified user id belong to the group admin or not.
* @param um
* @param groupId
* @param userId
* @return
* @throws RepositoryException
*/
public static boolean isMember(final UserManager um, final String groupId, final String userId)
throws RepositoryException {
if (StringUtils.isNotEmpty(groupId) && StringUtils.isNotEmpty(userId)) {
final Authorizable user = um.getAuthorizable(userId);
final Authorizable group = um.getAuthorizable(groupId);
if (group instanceof Group && user != null) {
return ((Group) group).isMember(user);
}
}
return false;
}
public static boolean isGroupAdmin(final Session session, final Resource resource) throws OperationException {
if (resource == null || session == null) {
return false;
}
// check the group configure first
final ResourceResolver resolver = resource.getResourceResolver();
final CommunityContext context = resource.adaptTo(CommunityContext.class);
final Resource configure = resolver.getResource(context.getSitePath());
if (configure == null) {
return false;
}
final ValueMap values = configure.adaptTo(ValueMap.class);
final String groupCreationType =
values.get(CommunitySiteConstants.PROP_CONFIG_GROUP_CREATION_PERMISSION_TYPE, String.class);
if (StringUtils.equalsIgnoreCase(groupCreationType,
SiteConfiguration.GroupManagementConfiguration.CreatePermission.EVERYONE.name())) {
if (ANONYMOUS_USER.equals(session.getUserID())) {
return false;
} else {
return true;
}
}
try {
Privilege[] userPrivs = session.getAccessControlManager().getPrivileges(resource.getPath());
if (userPrivs.length == 1 && UserUtils.JCR_ALL_PRIVELEGE.equalsIgnoreCase(userPrivs[0].getName())) {
return true;
} else {
return false;
}
} catch (final RepositoryException e) {
log.error("Error Check If User Is Group Admin " + session.getUserID(), e);
return false;
}
}
/**
* Check if logged in user can invite group members. when group creation permission type is everyone, only group
* owner and real admins can invite/promote/demote members
* @return true if logged in user can invite group members
*/
public static boolean canInviteGroupMember(final ResourceResolver resolver, final CommunityContext context) {
final Session session = resolver.adaptTo(Session.class);
if (context == null) {
return false;
}
final String groupPath = context.getCommunityGroupPath();
if (StringUtils.isEmpty(groupPath)) {
return false;
}
final Resource groupRes = resolver.resolve(groupPath);
final Resource groupConfig = groupRes.getChild(CommunityGroupConstants.CONFIG_NODE_NAME);
if (groupConfig == null) {
return false;
}
final ValueMap values = groupConfig.adaptTo(ValueMap.class);
if (values == null) {
return false;
}
final String type = values.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE, String.class);
final String owner = values.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_CREATOR, String.class);
if (!GroupConstants.TYPE_SECRET.equals(type)) {
return false;
}
// check the group configure first
final Resource siteConfigure = resolver.getResource(context.getSitePath());
if (siteConfigure == null) {
return false;
}
final ValueMap siteValues = siteConfigure.adaptTo(ValueMap.class);
final String groupCreationType =
siteValues.get(CommunitySiteConstants.PROP_CONFIG_GROUP_CREATION_PERMISSION_TYPE, String.class);
if (StringUtils.equalsIgnoreCase(groupCreationType,
SiteConfiguration.GroupManagementConfiguration.CreatePermission.EVERYONE.name())) {
if (session.getUserID().equals(owner)) {
return true;
}
}
try {
Privilege[] userPrivs = session.getAccessControlManager().getPrivileges(groupRes.getPath());
if (userPrivs.length == 1 && UserUtils.JCR_ALL_PRIVELEGE.equalsIgnoreCase(userPrivs[0].getName())) {
return true;
} else {
return false;
}
} catch (final RepositoryException e) {
log.error("Error Check If User Is Group Admin " + session.getUserID(), e);
return false;
}
}
/**
* Check if logged in user can invite group members. when group creation permission type is everyone, only group
* owner and real admins can invite/promote/demote members
* @return true if logged in user can invite group members
*/
public static boolean canLeaveGroup(final ResourceResolver resolver, final CommunityContext context) {
final Session session = resolver.adaptTo(Session.class);
if (context == null) {
return false;
}
final String groupPath = context.getCommunityGroupPath();
if (StringUtils.isEmpty(groupPath)) {
return false;
}
final Resource groupRes = resolver.resolve(groupPath);
final Resource groupConfig = groupRes.getChild(CommunityGroupConstants.CONFIG_NODE_NAME);
if (groupConfig == null) {
return false;
}
final ValueMap values = groupConfig.adaptTo(ValueMap.class);
if (values == null) {
return false;
}
final String owner = values.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_CREATOR, String.class);
// check the group configure first
final Resource siteConfigure = resolver.getResource(context.getSitePath());
if (siteConfigure == null) {
return false;
}
final ValueMap siteValues = siteConfigure.adaptTo(ValueMap.class);
final String groupCreationType =
siteValues.get(CommunitySiteConstants.PROP_CONFIG_GROUP_CREATION_PERMISSION_TYPE, String.class);
if (StringUtils.equalsIgnoreCase(groupCreationType,
SiteConfiguration.GroupManagementConfiguration.CreatePermission.EVERYONE.name())) {
if (session.getUserID().equals(owner)) {
return true;
}
}
try {
Privilege[] userPrivs = session.getAccessControlManager().getPrivileges(groupRes.getPath());
if (userPrivs.length == 1 && UserUtils.JCR_ALL_PRIVELEGE.equalsIgnoreCase(userPrivs[0].getName())) {
return true;
} else {
return false;
}
} catch (final RepositoryException e) {
log.error("Error Check If User Is Group Admin " + session.getUserID(), e);
return false;
}
}
/**
* Check if logged in user can promote group members. this is disabled when group creation permission type is
* everyone.
* @return true if logged in user can promote group members
*/
public static boolean canPromoteGroupMember(final ResourceResolver resolver, final CommunityContext context) {
final Session session = resolver.adaptTo(Session.class);
if (context == null) {
return false;
}
final String groupPath = context.getCommunityGroupPath();
if (StringUtils.isEmpty(groupPath)) {
return false;
}
final Resource groupRes = resolver.resolve(groupPath);
final Resource groupConfig = groupRes.getChild(CommunityGroupConstants.CONFIG_NODE_NAME);
if (groupConfig == null) {
return false;
}
final ValueMap values = groupConfig.adaptTo(ValueMap.class);
if (values == null) {
return false;
}
final String type = values.get(CommunityGroupConstants.PROP_COMMUNITY_GROUP_TYPE, String.class);
if (!GroupConstants.TYPE_SECRET.equals(type)) {
return false;
}
// check the group configure first
final Resource siteConfigure = resolver.getResource(context.getSitePath());
if (siteConfigure == null) {
return false;
}
final ValueMap siteValues = siteConfigure.adaptTo(ValueMap.class);
final String groupCreationType =
siteValues.get(CommunitySiteConstants.PROP_CONFIG_GROUP_CREATION_PERMISSION_TYPE, String.class);
if (StringUtils.equalsIgnoreCase(groupCreationType,
SiteConfiguration.GroupManagementConfiguration.CreatePermission.EVERYONE.name())) {
return false;
}
try {
Privilege[] userPrivs = session.getAccessControlManager().getPrivileges(groupRes.getPath());
if (userPrivs.length == 1 && UserUtils.JCR_ALL_PRIVELEGE.equalsIgnoreCase(userPrivs[0].getName())) {
return true;
} else {
return false;
}
} catch (final RepositoryException e) {
log.error("Error Check If User Is Group Admin " + session.getUserID(), e);
return false;
}
}
public static boolean canAccessCommunityGroup(final ResourceResolver resolver, final CommunityGroup group) {
if (GroupConstants.TYPE_OPEN.equalsIgnoreCase(group.getType())) {
return true;
} else {
// check if the session has access right
final String membergroup = group.getMemberGroupId();
final String currentUser = resolver.adaptTo(Session.class).getUserID();
return isMember(null, resolver, currentUser, membergroup);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy