enhancements on groups integration

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/widgets/workspace-sharing-widget@97630 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Francesco Mangiacrapa 2014-06-23 13:04:48 +00:00
parent e37736b893
commit 2d8f467022
8 changed files with 565 additions and 9 deletions

View File

@ -27,6 +27,8 @@ import org.gcube.portlets.widgets.workspacesharingwidget.shared.GXTFolderItemTyp
import org.gcube.portlets.widgets.workspacesharingwidget.shared.InfoContactModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.WorkspaceACL;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.WorkspaceACL.USER_TYPE;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VO;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VRE;
import org.gcube.vomanagement.usermanagement.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -109,8 +111,7 @@ public class GWTWorkspaceSharingBuilder {
* @return
* @throws InternalErrorException
*/
public List<InfoContactModel> buildGXTListContactsModelFromGcubeGroup(
List<GCubeGroup> list) throws InternalErrorException {
public List<InfoContactModel> buildGXTListContactsModelFromGcubeGroup(List<GCubeGroup> list) throws InternalErrorException {
List<InfoContactModel> listContactsModel = new ArrayList<InfoContactModel>();
@ -154,6 +155,47 @@ public class GWTWorkspaceSharingBuilder {
return listContactsModel;
}
/**
*
* @param list
* @return
* @throws InternalErrorException
*/
public List<InfoContactModel> buildGXTListContactsModelFromVOs(List<VO> listVO) throws InternalErrorException {
List<InfoContactModel> listContactsModel = new ArrayList<InfoContactModel>();
if (listVO == null){
logger.warn("List<VO> is null, returning");
return listContactsModel;
}
logger.trace("List<VO> size is: "+ listVO.size());
logger.trace("Building list contact model...");
for (VO vo : listVO) {
List<VRE> vres = vo.getVres();
if(vres!=null){
logger.trace("vres from VO "+vo.getName() +" having size :" +vres.size() +", converting");
for (VRE vre : vres) {
if(vre.getName()!=null || !vre.getName().isEmpty()){
InfoContactModel contact = new InfoContactModel(vre.getName(), vre.getName(), vre.getName(), true);
logger.trace("Adding VRE " + contact);
listContactsModel.add(contact);
}
}
}else
logger.trace("vres list is null, skipping VO "+vo.getName());
}
logger.trace("List GCubeGroup contact model completed, return "
+ listContactsModel.size() + " contacts");
return listContactsModel;
}
public List<InfoContactModel> buildGXTListContactsModelFromUserModel(
List<UserModel> listUsers) throws InternalErrorException {

View File

@ -19,6 +19,7 @@ import org.gcube.common.homelibrary.home.workspace.exceptions.ItemAlreadyExistEx
import org.gcube.common.homelibrary.home.workspace.exceptions.WorkspaceFolderNotFoundException;
import org.gcube.common.homelibrary.home.workspace.exceptions.WrongDestinationException;
import org.gcube.common.homelibrary.home.workspace.usermanager.GCubeGroup;
import org.gcube.common.portal.PortalContext;
import org.gcube.portlets.widgets.workspacesharingwidget.client.ConstantsSharing;
import org.gcube.portlets.widgets.workspacesharingwidget.client.rpc.WorkspaceSharingService;
import org.gcube.portlets.widgets.workspacesharingwidget.server.notifications.NotificationsProducer;
@ -31,6 +32,7 @@ import org.gcube.portlets.widgets.workspacesharingwidget.shared.FileModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.InfoContactModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.SessionExpiredException;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.WorkspaceACL;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VO;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
@ -78,7 +80,7 @@ public class WorkspaceSharingServiceImpl extends RemoteServiceServlet implements
public List<InfoContactModel> getAllContacts(boolean readGroupsFromHL, boolean readGroupsFromPortal) throws Exception {
try {
WsUtil.getAslSession(this.getThreadLocalRequest().getSession()); //THIS FORCE THE SESSION CREATION
ASLSession aslSession = WsUtil.getAslSession(this.getThreadLocalRequest().getSession()); //THIS FORCE THE SESSION CREATION
logger.info("Get all contacts");
// WorkspaceItem parent = workspace.getItem(parentFileModel.getIdentifier()); //get item from workspace
@ -107,7 +109,7 @@ public class WorkspaceSharingServiceImpl extends RemoteServiceServlet implements
UserManager userManag = new LiferayUserManager();
GroupManager gm = new LiferayGroupManager();
String groupId = gm.getRootVO().getGroupId();
logger.trace("Liferay User Manager getting list users by group: "+groupId);
List<InfoContactModel> listContactsModel = builder.buildGXTListContactsModelFromUserModel(userManag.listUsersByGroup(groupId));
@ -117,14 +119,20 @@ public class WorkspaceSharingServiceImpl extends RemoteServiceServlet implements
logger.trace("Home Library User Manager getting list Gcube Group");
List<GCubeGroup> groups = hlUserManager.getGroups();
if(groups!=null){
logger.info("Read group names from HL, return "+groups.size()+" groups, noewconverting");
logger.info("Read group names from HL, return "+groups.size()+" groups, converting");
listContactsModel.addAll(builder.buildGXTListContactsModelFromGcubeGroup(groups));
}else
logger.warn("Read group names from HL, return list null, skipping");
}
if(readGroupsFromPortal){
logger.info("Reading group names as scopes from Infrastructure..");
PortalContext context = PortalContext.getConfiguration();
logger.info("context.getInfrastructureName(): "+context.getInfrastructureName());
logger.info("aslSession.getScope(): "+ aslSession.getScope());
List<VO> lsVOs = WsUtil.getVresFromInfrastructure(context.getInfrastructureName(), aslSession.getScope());
listContactsModel.addAll(builder.buildGXTListContactsModelFromVOs(lsVOs));
}
@ -442,4 +450,22 @@ public class WorkspaceSharingServiceImpl extends RemoteServiceServlet implements
}
public static void main(String[] args) {
WorkspaceSharingServiceImpl impl = new WorkspaceSharingServiceImpl();
try {
PortalContext context = PortalContext.getConfiguration();
System.out.println("context.getInfrastructureName(): "+context.getInfrastructureName());
System.out.println("context.getVOsAsString(): "+context.getVOsAsString());
List<VO> vos = WsUtil.getVresFromInfrastructure(context.getInfrastructureName(), context.getVOsAsString());
for (VO vo : vos) {
System.out.println("vo name "+vo.getName());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,262 @@
package org.gcube.portlets.widgets.workspacesharingwidget.server.util;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.gcube.common.resources.gcore.GenericResource;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.UserBelonging;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VO;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VRE;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
* @version 2.0 Jan 10th 2012
*
* changed by Francesco Mangiacrapa
*/
public class LoginServiceUtil {
/**
*
*/
public static final String ROOT_ORG = "rootorganization";
/**
*
*/
public static final String PUBLIC_LAYOUT_NAME = " Data e-Infrastructure gateway";
/**
*
*/
public static final String GUEST_COMMUNITY_NAME = "Guest";
private static final Logger _log = LoggerFactory.getLogger(LoginServiceUtil.class);
/**
*
* @param screenName
* @param organizatioId
* @return
*/
protected static boolean checkPending(String screenName, long organizationId) {
try {
for (UserModel userModel : new LiferayUserManager().listPendingUsersByGroup(""+organizationId))
if (userModel.getScreenName().compareTo(screenName) == 0) return true;
} catch (UserManagementSystemException e) {
e.printStackTrace();
} catch (GroupRetrievalFault e) {
e.printStackTrace();
} catch (UserRetrievalFault e) {
e.printStackTrace();
}
return false;
}
/**
* add a property to gcube-data.properties for root vo, it make the login portlet understand the installation was setup already
* @param rootVoName .
*/
protected static void appendRootOrganizationName(String rootVoName) {
Properties props = new Properties();
try {
String propertyfile = OrganizationsUtil.getTomcatFolder()+"conf/gcube-data.properties";
File propsFile = new File(propertyfile);
FileInputStream fis = new FileInputStream(propsFile);
props.load( fis);
props.setProperty(ROOT_ORG, rootVoName);
FileOutputStream fos = new FileOutputStream(propsFile);
props.store(fos, null);
}
//catch exception in case properties file does not exist
catch(IOException e) {
e.printStackTrace();
}
_log.info("Added property Root VO Name: " + rootVoName );
}
/**
* read the root VO name from a property file and retuns it
*/
protected static String getRootOrganizationName() {
//get the portles to look for from the property file
Properties props = new Properties();
String toReturn = "";
try {
String propertyfile = OrganizationsUtil.getTomcatFolder()+"conf/gcube-data.properties";
File propsFile = new File(propertyfile);
FileInputStream fis = new FileInputStream(propsFile);
props.load( fis);
toReturn = props.getProperty(ROOT_ORG);
}
//catch exception in case properties file does not exist
catch(IOException e) {
toReturn = "gcube";
_log.error("gcube-data.properties file not found under $CATALINA_HOME/conf dir, returning default VO Name " + toReturn);
return toReturn;
}
_log.debug("Returning Root VO Name: " + toReturn );
return toReturn;
}
/**
* simply returns fake VOS for debugging purpose
* @return
*/
protected static List<VO> getFakeVOs() {
VO rootVO = new VO();
rootVO.setRoot(true);
rootVO.setName("/d4science.research-infrastructures.eu/");
rootVO.setDescription("This is the description for the ROOT VO");
rootVO.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/RedGrid.jpg");
rootVO.setUserBelonging(UserBelonging.BELONGING);
/***************************************/
VO emVO = new VO();
emVO.setRoot(false);
emVO.setGroupName("/d4science.research-infrastructures.eu/EM/");
emVO.setName("EM VO");
emVO.setDescription("EM and AEM Virtual Organisation The FARM Virtual Organisation is the dynamic group of individuals and/or institutions defined around a set of sharing rules in which resource providers and consumers specify clearly and carefully just what is shared, who is allowed to share, and the conditions under which sharing occurs to serve the needs of the Fisheries and Aquaculture Resources Management.");
emVO.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/RedGrid.jpg");
emVO.setUserBelonging(UserBelonging.NOT_BELONGING);
//
//
VRE cool_EM_VRE = new VRE();
cool_EM_VRE.setName("COOL EM VRE");
cool_EM_VRE.setGroupName("/d4science.research-infrastructures.eu/EM/COOLEMVRE");
cool_EM_VRE.setDescription("cool_EM_VRE VRE Description<br />"+
"This Virtual Research Environment is for cool authors, managers and researchers who produce reports containing cool data.");
cool_EM_VRE.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/gcm-preview.jpg");
cool_EM_VRE.setUserBelonging(UserBelonging.BELONGING);
emVO.addVRE(cool_EM_VRE);
VRE cool_EM_VRE2 = new VRE();
cool_EM_VRE2.setName("COOL VRE 2");
cool_EM_VRE2.setGroupName("/d4science.research-infrastructures.eu/EM/COOLEMVRE2");
cool_EM_VRE2.setDescription("Cool VRE Description<br />"+
"This Virtual Research Environment is for cool authors, managers and researchers who produce reports containing cool data.");
cool_EM_VRE2.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/aquamaps-preview.jpg");
cool_EM_VRE2.setUserBelonging(UserBelonging.NOT_BELONGING);
VRE cool_EM_VRE3 = new VRE();
cool_EM_VRE3.setName("COOL EM VRE TRE");
cool_EM_VRE3.setGroupName("/d4science.research-infrastructures.eu/EM/COOlVRE3");
cool_EM_VRE3.setDescription("Cool VRE Description<br />"+
"This Virtual Research Environment is for cool authors, managers and researchers who produce reports containing cool data.");
cool_EM_VRE3.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/aquamaps-preview.jpg");
cool_EM_VRE3.setUserBelonging(UserBelonging.BELONGING);
VRE demo = new VRE();
demo.setName("Demo");
demo.setGroupName("/d4science.research-infrastructures.eu/EM/Demo");
demo.setDescription("Cool VRE Description<br />"+
"This Virtual Research Environment is for cool authors, managers and researchers who produce reports containing cool data.");
demo.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/RedGrid.jpg");
demo.setUserBelonging(UserBelonging.BELONGING);
VRE vreGCM = new VRE();
vreGCM.setName("GCM");
vreGCM.setGroupName("/d4science.research-infrastructures.eu/EM/GCM");
vreGCM.setDescription("Global Ocean Chlorophyll Monitoring (GCM) Virtual Research Environment<br />"
+ "The phytoplankton plays a similar role to terrestrial green plants in the photosynthetic process and are credited with removing as much carbon dioxide from the atmosphere as their earthbound counterparts, making it important to monitor and model plankton into calculations of future climate change.");
vreGCM.setImageURL("http://portal.d4science.research-infrastructures.eu/vologin/html/aquamaps-preview.jpg");
vreGCM.setUserBelonging(UserBelonging.BELONGING);
emVO.addVRE(cool_EM_VRE);
emVO.addVRE(cool_EM_VRE2);
emVO.addVRE(cool_EM_VRE3);
emVO.addVRE(demo);
emVO.addVRE(vreGCM);
ArrayList<VO> toReturn = new ArrayList<VO>();
toReturn.add(rootVO);
toReturn.add(emVO);
toReturn.add(emVO);
return toReturn;
}
/**
*
* @param scopename a string
* @return true if any VRE Exists
*/
protected static Boolean checkVresPresence(String scopename) {
ScopeBean scope = null;
scope = new ScopeBean("/"+scopename);
try {
_log.info("Searching for VREs into " + scope.name());
String currScope = ScopeProvider.instance.get();
ScopeProvider.instance.set(scope.toString());
SimpleQuery query = queryFor(GenericResource.class);
query.addCondition("$resource/Profile/SecondaryType/text() eq '"+ Type.VRE +"'");
DiscoveryClient<GenericResource> client = clientFor(GenericResource.class);
boolean result = client.submit(query).size() > 0;
ScopeProvider.instance.set(currScope);
return result;
} catch (Exception e) {
_log.error("Generic Exception for " + scope.name() + " " + e.getMessage());
e.printStackTrace();
return null;
}
}
/**
*
* @param scopename a string
* @return an arraylist of <class>VRE</class> with just name and description filled
*/
protected static List<VRE> getVREsFromInfrastructure(String scopename) {
List<VRE> toReturn = new ArrayList<VRE>();
ScopeBean scope = null;
scope = new ScopeBean("/"+scopename);
try {
_log.info("Searching for VREs into " + scope.name());
String currScope = ScopeProvider.instance.get();
ScopeProvider.instance.set(scope.toString());
SimpleQuery query = queryFor(GenericResource.class);
query.addCondition("$resource/Profile/SecondaryType/text() eq '"+ Type.VRE +"'");
DiscoveryClient<GenericResource> client = clientFor(GenericResource.class);
for (GenericResource genres : client.submit(query)) {
toReturn.add(new VRE(genres.profile().name(), genres.profile().description(), "", "", "", null));
}
ScopeProvider.instance.set(currScope);
return toReturn;
} catch (Exception e) {
e.printStackTrace();
_log.error("Generic Exception for " + scope.name() + " " + e.getMessage());
return null;
}
}
}

View File

@ -3,11 +3,12 @@
*/
package org.gcube.portlets.widgets.workspacesharingwidget.server.util;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.gcube.application.framework.core.session.ASLSession;
import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
@ -22,6 +23,10 @@ import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
import org.gcube.portlets.widgets.workspacesharingwidget.server.GWTWorkspaceSharingBuilder;
import org.gcube.portlets.widgets.workspacesharingwidget.server.notifications.NotificationsProducer;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.InfoContactModel;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VO;
import org.gcube.portlets.widgets.workspacesharingwidget.shared.system.VRE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
@ -80,7 +85,6 @@ public class WsUtil {
logger.warn("USERNAME_ATTRIBUTE: "+USERNAME_ATTRIBUTE);
session = SessionManager.getInstance().getASLSession(sessionID, user);
session.setScope(TEST_SCOPE);
//MANDATORY FOR SOCIAL LIBRARY
session.setUserAvatarId(user + "Avatar");
@ -137,6 +141,36 @@ public class WsUtil {
}
/**
*
* @param infrastructure the infrastructure name
* @param startScopes the starting scopes
* @return an arraylist of <class>VO</class> containing their child VREs
*/
public static List<VO> getVresFromInfrastructure(String infrastructure, String startScopes) {
List<VO> toReturn = new ArrayList<VO>();
String[] organizations;
if (startScopes.contains(",")) {
organizations = startScopes.split(",");
for (int i = 0; i < organizations.length; i++) {
VO toAdd = new VO();
toAdd.setName(organizations[i]);
toAdd.setVres((ArrayList<VRE>) LoginServiceUtil.getVREsFromInfrastructure(infrastructure+"/"+organizations[i]));
toReturn.add(toAdd);
}
}
else {
organizations = new String[1];
organizations[0] = startScopes;
VO toAdd = new VO();
toAdd.setName(organizations[0]);
toAdd.setVres((ArrayList<VRE>) LoginServiceUtil.getVREsFromInfrastructure(infrastructure+"/"+organizations[0]));
toReturn.add(toAdd);
}
return toReturn;
}
public static Workspace getWorkspace(final HttpSession httpSession) throws InternalErrorException, HomeNotFoundException, WorkspaceFolderNotFoundException
{

View File

@ -0,0 +1,87 @@
package org.gcube.portlets.widgets.workspacesharingwidget.shared.system;
import java.io.Serializable;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
* @version 2.0 Jan 10th 2012
*/
@SuppressWarnings("serial")
public class ResearchEnvironment implements Serializable{
private String name;
private String description;
private String imageURL;
private String groupName;
private String friendlyURL;
private UserBelonging userBelonging;
public ResearchEnvironment() {
super();
}
public ResearchEnvironment(String name, String description,
String imageURL, String groupName, String friendlyURL,
UserBelonging userBelonging) {
super();
this.name = name;
this.description = description;
this.imageURL = imageURL;
this.groupName = groupName;
this.friendlyURL = friendlyURL;
this.userBelonging = userBelonging;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImageURL() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getFriendlyURL() {
return friendlyURL;
}
public void setFriendlyURL(String friendlyURL) {
this.friendlyURL = friendlyURL;
}
public UserBelonging getUserBelonging() {
return userBelonging;
}
public void setUserBelonging(UserBelonging userBelonging) {
this.userBelonging = userBelonging;
}
}

View File

@ -0,0 +1,5 @@
package org.gcube.portlets.widgets.workspacesharingwidget.shared.system;
public enum UserBelonging { BELONGING, NOT_BELONGING, PENDING
}

View File

@ -0,0 +1,70 @@
package org.gcube.portlets.widgets.workspacesharingwidget.shared.system;
import java.io.Serializable;
import java.util.ArrayList;
/**
*
* @author Massimiliano Assante ISTI-CNR
*
* @version 2.0 Jan 10th 2012
*/
@SuppressWarnings("serial")
public class VO extends ResearchEnvironment implements Comparable<VO>, Serializable{
private boolean isRoot;
private ArrayList<VRE> vres = new ArrayList<VRE>();
/**
*
*/
public VO() {
super();
}
/**
*
* @param voName .
* @param description .
* @param imageURL .
* @param vomsGroupName .
* @param friendlyURL .
* @param userBelonging .
* @param isRoot .
* @param vres .
*/
public VO(String voName, String description, String imageURL,
String vomsGroupName, String friendlyURL,
UserBelonging userBelonging, boolean isRoot, ArrayList<VRE> vres) {
super(voName, description, imageURL, vomsGroupName, friendlyURL, userBelonging);
this.isRoot = isRoot;
this.vres = vres;
}
public boolean isRoot() {
return isRoot;
}
public void setRoot(boolean isRoot) {
this.isRoot = isRoot;
}
public ArrayList<VRE> getVres() {
return vres;
}
public void setVres(ArrayList<VRE> vres) {
this.vres = vres;
}
/**
*
* @param toAdd
*/
public void addVRE(VRE toAdd) {
if (vres == null)
vres = new ArrayList<VRE>();
vres.add(toAdd);
}
/**
* compare the number of vres
*/
public int compareTo(VO voToCompare) {
return (this.vres.size() >= voToCompare.getVres().size()) ? 1 : -1;
}
}

View File

@ -0,0 +1,30 @@
package org.gcube.portlets.widgets.workspacesharingwidget.shared.system;
import java.io.Serializable;
@SuppressWarnings("serial")
public class VRE extends ResearchEnvironment implements Serializable {
/**
*
*/
public VRE() {
super();
// TODO Auto-generated constructor stub
}
/**
*
* @param vreName
* @param description
* @param imageURL
* @param vomsGroupName
* @param friendlyURL
* @param userBelonging
*/
public VRE(String vreName, String description, String imageURL,
String vomsGroupName, String friendlyURL,
UserBelonging userBelonging) {
super(vreName, description, imageURL, vomsGroupName, friendlyURL, userBelonging);
}
}