package org.sakaiproject.site.tool.helper.managegroupsectionrole.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.authz.api.AuthzGroup; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.GroupNotDefinedException; import org.sakaiproject.authz.api.Member; import org.sakaiproject.authz.api.Role; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.event.cover.EventTrackingService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.util.Participant; import org.sakaiproject.site.util.SiteConstants; import org.sakaiproject.site.util.SiteParticipantHelper; import org.sakaiproject.tool.api.SessionManager; import org.sakaiproject.tool.api.Tool; import org.sakaiproject.tool.api.ToolManager; import org.sakaiproject.tool.api.ToolSession; import uk.org.ponder.messageutil.TargettedMessage; import uk.org.ponder.messageutil.TargettedMessageList; /** * * @author * */ public class SiteManageGroupSectionRoleHandler { /** Our log (commons). */ private static Log M_log = LogFactory.getLog(SiteManageGroupSectionRoleHandler.class); private List<Member> groupMembers; private GroupComparator groupComparator = new GroupComparator(); public Site site = null; public SiteService siteService = null; public AuthzGroupService authzGroupService = null; public ToolManager toolManager = null; public SessionManager sessionManager = null; public ServerConfigurationService serverConfigurationService; private List<Group> groups = null; private Set unhideables = null; public String memberList = ""; public boolean update = false; public boolean done = false; public String[] selectedGroupMembers = new String[]{}; public String[] selectedSiteMembers = new String[]{}; // selected rosters for autocreate groups public Map<String, Boolean> selectedRosters = new HashMap<String, Boolean>(); // selected roles for autocreate groups public Map<String, Boolean> selectedRoles = new HashMap<String, Boolean>(); private String NULL_STRING = ""; private final String TOOL_CFG_FUNCTIONS = "functions.require"; private final String TOOL_CFG_MULTI = "allowMultiple"; private final String SITE_UPD = "site.upd"; private final String HELPER_ID = "sakai.tool.helper.id"; private final String UNHIDEABLES_CFG = "poh.unhideables"; private final String GROUP_ADD = "group.add"; private final String GROUP_DELETE = "group.delete"; private final String GROUP_RENAME = "group.rename"; private final String GROUP_SHOW = "group.show"; private final String GROUP_HIDE = "group.hide"; private final String SITE_REORDER = "group.reorder"; private final String SITE_RESET = "group.reset"; // Tool session attribute name used to schedule a whole page refresh. public static final String ATTR_TOP_REFRESH = "sakai.vppa.top.refresh"; public TargettedMessageList messages; public void setMessages(TargettedMessageList messages) { this.messages = messages; } private void resetTargettedMessageList() { this.messages = new TargettedMessageList(); } private org.sakaiproject.authz.api.GroupProvider groupProvider = (org.sakaiproject.authz.api.GroupProvider) ComponentManager.get(org.sakaiproject.authz.api.GroupProvider.class); // the group title private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } // group title private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } // group description private String description; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } // for those to be deleted groups public String[] deleteGroupIds; /** * reset the variables */ public void resetParams() { id = ""; title = ""; description =""; deleteGroupIds=new String[]{}; selectedGroupMembers = new String[]{}; selectedSiteMembers = new String[]{}; selectedRosters = new HashMap<String, Boolean>(); selectedRoles = new HashMap<String, Boolean>(); } /** * Gets the groups for the current site * @return Map of groups (id, group) */ public List<Group> getGroups() { if (site == null) { init(); } if (update) { groups = new Vector<Group>(); if (site != null) { // only show groups created by WSetup tool itself Collection allGroups = (Collection) site.getGroups(); for (Iterator gIterator = allGroups.iterator(); gIterator.hasNext();) { Group gNext = (Group) gIterator.next(); String gProp = gNext.getProperties().getProperty( SiteConstants.GROUP_PROP_WSETUP_CREATED); if (gProp != null && gProp.equals(Boolean.TRUE.toString())) { groups.add(gNext); } } } } Collections.sort(groups, groupComparator); return groups; } /** * Gets the rosters for the current site excluding the group * @return List of roster ids */ public List<String> getSiteRosters(Group group) { if (site == null) { init(); } List<String> providerIds = null; if (update) { providerIds = new Vector<String>(); if (site != null) { // get all provider ids Set pIds = authzGroupService.getProviderIds(siteService.siteReference(site.getId())); providerIds.addAll(pIds); if (group != null) { Set groupPIds = authzGroupService.getProviderIds(siteService.siteGroupReference(site.getId(), group.getId())); providerIds.removeAll(groupPIds); } } } return providerIds; } /** * Gets the rosters for the group * @return List of roster ids */ public List<String> getGroupRosters(Group g) { List<String> providerIds = null; if (update) { providerIds = new Vector<String>(); if (g != null) { // get all provider ids Set pIds = authzGroupService.getProviderIds(siteService.siteGroupReference(site.getId(), g.getId())); providerIds.addAll(pIds); } } return providerIds; } /** * Gets the roles for the current site excluding the group * @return Map of groups (id, group) */ public List<Role> getSiteRoles(Group group) { if (site == null) { init(); } List<Role> roles = null; if (update) { roles = new Vector<Role>(); if (site != null) { // get the authz group String siteReference = siteService.siteReference(site.getId()); try { AuthzGroup siteGroup = authzGroupService.getAuthzGroup(siteReference); roles.addAll(siteGroup.getRoles()); } catch (GroupNotDefinedException e) { M_log.debug(this + ".getRoles: no authzgroup found for " + siteReference); } if (group != null) { String roleProviderId = group.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID); if (roleProviderId != null) { if (groupProvider != null) { String[] groupProvidedRoles = groupProvider.unpackId(roleProviderId); for(int i=0; i<groupProvidedRoles.length;i++) { roles.remove(group.getRole(groupProvidedRoles[i])); } } } } } } return roles; } /** * Gets the role ids for the current site * @return Map of groups (id, group) */ public List<String> getSiteRoleIds() { List<String> rv = new Vector<String>(); List<Role> roles = getSiteRoles(null); if (roles != null) { for(Role r:roles) { rv.add(r.getId()); } } return rv; } public boolean isUserFromProvider(String userEId, String userId, Group g, List<String> rosterIds, List<String> roleIds) { boolean rv = false; // check roster first if (rosterIds != null) { for (int i = 0; !rv && i < rosterIds.size(); i++) { if (groupProvider != null) { String providerId = rosterIds.get(i); Map userRole = groupProvider.getUserRolesForGroup(providerId); if (userRole.containsKey(userEId)) { rv = true; } } } } // check role next if (!rv && roleIds != null) { for (int i = 0; !rv && i < roleIds.size(); i++) { String roleId = roleIds.get(i); if (g.getUserRole(userId).getId().equals(roleId)) { rv = true; } } } return rv; } /** * Gets the roles for the group * @return Map of groups (id, group) */ public List<String> getGroupProviderRoles(Group g) { List<String> rv = null; if (update) { rv = new Vector<String>(); if (g != null) { // get the authz group String roleProviderId = g.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID); if (roleProviderId != null) { if (groupProvider != null) { String[] roleStrings = groupProvider.unpackId(roleProviderId); for(String roleString:roleStrings) { rv.add(roleString); } } } } } return rv; } /** * Initialization method, just gets the current site in preperation for other calls * */ public void init() { if (site == null) { String siteId = null; try { siteId = sessionManager.getCurrentToolSession() .getAttribute(HELPER_ID + ".siteId").toString(); } catch (java.lang.NullPointerException npe) { // Site ID wasn't set in the helper call!! } if (siteId == null) { siteId = toolManager.getCurrentPlacement().getContext(); } try { site = siteService.getSite(siteId); // allow update site or group membership update = siteService.allowUpdateSite(site.getId()) || siteService.allowUpdateGroupMembership(site.getId()); } catch (IdUnusedException e) { // The siteId we were given was bogus e.printStackTrace(); } } title = ""; String conf = serverConfigurationService.getString(UNHIDEABLES_CFG); if (conf != null) { unhideables = new HashSet(); String[] toolIds = conf.split(","); for (int i = 0; i < toolIds.length; i++) { unhideables.add(toolIds[i].trim()); } } if (groupMembers == null) { groupMembers = new Vector<Member>(); } } /** * Wrapper around siteService to save a site * @param site * @throws IdUnusedException * @throws PermissionException */ public void saveSite(Site site) throws IdUnusedException, PermissionException { siteService.save(site); } public List<Participant> getSiteParticipant(Group group) { List<Participant> rv = new Vector<Participant>(); if (site != null) { String siteId = site.getId(); String realmId = siteService.siteReference(siteId); List<String> providerCourseList = SiteParticipantHelper.getProviderCourseList(siteId); Collection<Participant> rvCopy = SiteParticipantHelper.prepareParticipants(siteId, providerCourseList); // check with group attendents if (group != null) { // need to remove those inside group already for(Participant p:rvCopy) { if (p.getUniqname() != null && group.getMember(p.getUniqname()) == null) { rv.add(p); } } } else { // if the group is null, add all site members rv.addAll(rvCopy); } } return rv; } public List<Member> getGroupParticipant() { return groupMembers; } /** * Allows the Cancel button to return control to the tool calling this helper * */ public String processCancel() { // reset the warning messages resetTargettedMessageList(); ToolSession session = sessionManager.getCurrentToolSession(); session.setAttribute(ATTR_TOP_REFRESH, Boolean.TRUE); return "done"; } /** * Cancel out of the current action and go back to main view * */ public String processBack() { // reset the warning messages resetTargettedMessageList(); return "cancel"; } public String reset() { try { siteService.save(site); EventTrackingService.post( EventTrackingService.newEvent(SITE_RESET, "/site/" + site.getId(), false)); } catch (IdUnusedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (PermissionException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ""; } /** * Adds a new group to the current site * @param toolId * @param title * @return the newly added Group */ public String processAddGroup () { // reset the warning message resetTargettedMessageList(); Group group = null; id = StringUtils.trimToNull(id); String siteReference = siteService.siteReference(site.getId()); if (title != null && title.length() > SiteConstants.SITE_GROUP_TITLE_LIMIT) { messages.addMessage(new TargettedMessage("site_group_title_length_limit",new Object[] { String.valueOf(SiteConstants.SITE_GROUP_TITLE_LIMIT) }, TargettedMessage.SEVERITY_ERROR)); return null; } else if (id == null) { Collection siteGroups = site.getGroups(); if (siteGroups != null && siteGroups.size() > 0) { // when adding a group, check whether the group title has // been used already boolean titleExist = false; for (Iterator iGroups = siteGroups.iterator(); !titleExist && iGroups.hasNext();) { Group iGroup = (Group) iGroups.next(); if (title.equals(iGroup.getTitle())) { // found same title titleExist = true; } } if (titleExist) { messages.addMessage(new TargettedMessage("group.title.same", null, TargettedMessage.SEVERITY_ERROR)); return null; } } } if (id != null) { // editing existing group group = site.getGroup(id); } else { // adding a new group group= site.addGroup(); group.getProperties().addProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString()); } if (group != null) { group.setTitle(title); group.setDescription(description); boolean found = false; // remove those no longer included in the group Set members = group.getMembers(); String[] membersSelected = (memberList != null && memberList.length() > 0) ? memberList.split("##"):new String[0]; for (Iterator iMembers = members.iterator(); iMembers .hasNext();) { found = false; String mId = ((Member) iMembers.next()).getUserId(); for (int i = 0; !found && i < membersSelected.length; i++) { if (mId.equals(membersSelected[i])) { found = true; } } if (!found) { group.removeMember(mId); } } // add those seleted members List<String> siteRosters = getSiteRosters(null); List<String> siteRoles = getSiteRoleIds(); List<String> selectedRosters = new Vector<String>(); List<String> selectedRoles = new Vector<String>(); for (int i = 0; i < membersSelected.length; i++) { String memberId = membersSelected[i]; if (siteRosters.contains(memberId)) { // this is a roster selectedRosters.add(memberId); } else if (siteRoles.contains(memberId)) { // this is a role Set roleUsers = site.getUsersHasRole(memberId); for (Iterator iRoleUsers = roleUsers.iterator(); iRoleUsers.hasNext();) { String roleUserId = (String) iRoleUsers.next(); Member member = site.getMember(roleUserId); group.addMember(roleUserId, memberId, member.isActive(), false); } selectedRoles.add(memberId); } else { // normal user id memberId = StringUtils.trimToNull(memberId); if (memberId != null && group.getUserRole(memberId) == null) { Role r = site.getUserRole(memberId); Member m = site.getMember(memberId); Role memberRole = m != null ? m.getRole() : null; // for every member added through the "Manage // Groups" interface, he should be defined as // non-provided // get role first from site definition. // However, if the user is inactive, getUserRole would return null; then use member role instead group.addMember(memberId, r != null ? r.getId() : memberRole != null? memberRole.getId() : "", m != null ? m.isActive() : true, false); } } } if (!selectedRosters.isEmpty()) { // set provider id group.setProviderGroupId(getProviderString(selectedRosters)); } else { // clear the provider id group.setProviderGroupId(null); } if (!selectedRoles.isEmpty()) { // pack the role provider id and add to property group.getProperties().addProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID, getProviderString(selectedRoles)); } else { // clear the role provider id group.getProperties().removeProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID); } // save the changes try { siteService.save(site); // reset the form params resetParams(); } catch (IdUnusedException e) { M_log.warn(this + ".processAddGroup: cannot find site " + site.getId(), e); return null; } catch (PermissionException e) { M_log.warn(this + ".processAddGroup: cannot find site " + site.getId(), e); return null; } } return "success"; } public String processConfirmGroupDelete() { // reset the warning messages resetTargettedMessageList(); if (deleteGroupIds == null || deleteGroupIds.length == 0) { // no group chosen to be deleted M_log.debug(this + ".processConfirmGroupDelete: no group chosen to be deleted."); messages.addMessage(new TargettedMessage("delete_group_nogroup","no group chosen")); return null; } else { List<Group> groups = new Vector<Group>(); for (int i = 0; i < deleteGroupIds.length; i ++) { String groupId = deleteGroupIds[i]; // try { Group g = site.getGroup(groupId); groups.add(g); } catch (Exception e) { } } return "confirm"; } } public String processDeleteGroups() { // reset the warning messages resetTargettedMessageList(); if (site != null) { for (int i = 0; i < deleteGroupIds.length; i ++) { String groupId = deleteGroupIds[i]; Group g = site.getGroup(groupId); if (g != null) { site.removeGroup(g); } } try { siteService.save(site); } catch (IdUnusedException e) { messages.addMessage(new TargettedMessage("editgroup.site.notfound.alert","cannot find site")); M_log.warn(this + ".processDeleteGroups: Problem of saving site after group removal: site id =" + site.getId(), e); } catch (PermissionException e) { messages.addMessage(new TargettedMessage("editgroup.site.permission.alert","not allowed to find site")); M_log.warn(this + ".processDeleteGroups: Permission problem of saving site after group removal: site id=" + site.getId(), e); } } return "success"; } public String processCancelDelete() { // reset the warning messages resetTargettedMessageList(); return "cancel"; } /** * atuo create group(s) based on selected roster(s) or role(s) * */ public String processAutoCreateGroup() { // reset the warning messages resetTargettedMessageList(); List<String> rosterList = new Vector<String>(); if (!selectedRosters.isEmpty()) { for (Iterator<String> iterRosters= selectedRosters.keySet().iterator(); iterRosters.hasNext(); ) { String roster = iterRosters.next(); if (selectedRosters.get(roster) == Boolean.TRUE) { // selected roster rosterList.add(roster); } } } List<String> roleList = new Vector<String>(); if (!selectedRoles.isEmpty()) { for (Iterator<String> iterRoles = selectedRoles.keySet().iterator(); iterRoles.hasNext(); ) { String role = iterRoles.next(); if (selectedRoles.get(role) == Boolean.TRUE) { // selected role roleList.add(role); } } } if (rosterList.isEmpty() && roleList.isEmpty()) { // nothing selected, generate alert messages.addMessage(new TargettedMessage("group.autocreate.selectrosterorrole","Please select at lease one roster or role.")); } else { // go and create the new group if (!rosterList.isEmpty()) { for (String roster:rosterList) { Group group = site.addGroup(); group.getProperties().addProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString()); // roster provider string group.setProviderGroupId(roster); String title = truncateGroupTitle(roster); group.setTitle(title); } } // role based if (!roleList.isEmpty()) { for(String role:roleList) { Group group = site.addGroup(); // make the provider id as of SITEID_ROLEID //group.setProviderGroupId(site.getId() + "_" + role); group.getProperties().addProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString()); group.getProperties().addProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID, role); String title = truncateGroupTitle(role); group.setTitle(title); // get the authz group String siteReference = siteService.siteReference(site.getId()); try { AuthzGroup siteGroup = authzGroupService.getAuthzGroup(siteReference); Set<String> usersHasRole = siteGroup.getUsersHasRole(role); if (usersHasRole != null) { for (Iterator<String> uIterator = usersHasRole.iterator(); uIterator.hasNext();) { String userId = uIterator.next(); Member member = site.getMember(userId); group.addMember(userId, role, member.isActive(), false); } } } catch (GroupNotDefinedException e) { M_log.debug(this + ".processAutoCreateGroup: no authzgroup found for " + siteReference); } } } // save the changes try { siteService.save(site); // reset the form params resetParams(); } catch (IdUnusedException e) { M_log.warn(this + ".processAutoCreateGroup: cannot find site " + site.getId(), e); return null; } catch (PermissionException e) { M_log.warn(this + ".processAutoCreateGroup: cannot find site " + site.getId(), e); return null; } } return "done"; } /** * check whether the title string is within length limit, truncate it if necessary * @param oTitle * @return */ private String truncateGroupTitle(String oTitle) { String title = oTitle; if (title.length() > SiteConstants.SITE_GROUP_TITLE_LIMIT) { title = title.substring(0, SiteConstants.SITE_GROUP_TITLE_LIMIT); } return title.trim(); } /** * Return a single string representing the provider id list * @param idsList */ private String getProviderString(List<String> idsList) { String[] sArray = new String[idsList.size()]; sArray = (String[]) idsList.toArray(sArray); if (groupProvider != null) { return groupProvider.packId(sArray); } else { // simply concat strings StringBuffer rv = new StringBuffer(); for(String sArrayString:sArray) { rv.append(" ").append(sArrayString); } return rv.toString(); } } /** * Removes a group from the site * * @param groupId * @return title of page removed * @throws IdUnusedException * @throws PermissionException */ public String removeGroup(String groupId) throws IdUnusedException, PermissionException { Group group = site.getGroup(groupId); site.removeGroup(group); saveSite(site); EventTrackingService.post( EventTrackingService.newEvent(GROUP_DELETE, "/site/" + site.getId() + "/group/" + group.getId(), false)); return group.getTitle(); } public String[] getDeleteGroupIds() { return deleteGroupIds; } public List<Group> getSelectedGroups() { List<Group> rv = new Vector<Group>(); if (deleteGroupIds != null && deleteGroupIds.length > 0 && site != null) { for (int i = 0; i<deleteGroupIds.length; i++) { String groupId = deleteGroupIds[i]; try { Group g = site.getGroup(groupId); rv.add(g); } catch (Exception e) { M_log.debug(this + ":getSelectedGroups: cannot get group with id " + groupId); } } } return rv; } public void setDeleteGroupIds(String[] deleteGroupIds) { this.deleteGroupIds = deleteGroupIds; } /** * Gets the current tool * @return Tool */ public Tool getCurrentTool() { return toolManager.getCurrentTool(); } /** * check whether there is already a group within the site containing the roster id * @param rosterId * @return */ public boolean existRosterGroup(String rosterId) { boolean rv = false; Collection<Group> groups = site.getGroups(); for(Group group:groups) { // check if there is one group with this roster id already String groupWSetupCreated = group.getProperties().getProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED); if (groupWSetupCreated != null && groupWSetupCreated.equalsIgnoreCase(Boolean.TRUE.toString())) { if (group.getProviderGroupId() != null && group.getProviderGroupId().equals(rosterId)) { rv = true; break; } } } return rv; } /** * check whether there is already a group within the site containing the role id * @param roleId * @return */ public boolean existRoleGroup(String roleId) { boolean rv = false; Collection<Group> groups = site.getGroups(); for(Group group:groups) { // check if there is one group with this roster id already String groupWSetupCreated = group.getProperties().getProperty(SiteConstants.GROUP_PROP_WSETUP_CREATED); if (groupWSetupCreated != null && groupWSetupCreated.equalsIgnoreCase(Boolean.TRUE.toString())) { String groupRole = group.getProperties().getProperty(SiteConstants.GROUP_PROP_ROLE_PROVIDERID); if (groupRole != null && groupRole.equals(roleId)) { rv = true; break; } } } return rv; } /** ** Comparator for sorting Group objects **/ private class GroupComparator implements Comparator { public int compare(Object o1, Object o2) { return ((Group)o1).getTitle().compareToIgnoreCase( ((Group)o2).getTitle() ); } } }