/********************************************************************************** * $URL:https://source.sakaiproject.org/svn/osp/trunk/presentation/tool/src/java/org/theospi/portfolio/presentation/control/DeletePresentationController.java $ * $Id:DeletePresentationController.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $ *********************************************************************************** * * Copyright (c) 2008, 2009 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.theospi.portfolio.presentation.control; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.HashSet; import java.util.HashMap; import java.util.Comparator; import java.util.Collection; import java.util.Collections; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.metaobj.utils.mvc.intf.Controller; import org.sakaiproject.metaobj.shared.model.Id; import org.sakaiproject.metaobj.shared.model.Agent; import org.sakaiproject.metaobj.shared.mgt.AgentManager; import org.theospi.portfolio.security.Authorization; import org.springframework.validation.Errors; import org.springframework.web.servlet.ModelAndView; import org.theospi.portfolio.presentation.model.Presentation; import org.theospi.portfolio.security.AudienceSelectionHelper; import org.theospi.portfolio.presentation.support.AgentWrapper; import org.theospi.portfolio.presentation.support.PresentationService; import org.theospi.portfolio.presentation.support.PresentationShareUserService; import org.sakaiproject.authz.api.Member; import org.sakaiproject.authz.api.Role; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.tool.api.Session; import org.sakaiproject.util.ResourceLoader; import org.sakaiproject.email.api.EmailService; import org.sakaiproject.user.api.UserDirectoryService; /** **/ public class SharePresentationMoreController extends AbstractPresentationController implements Controller { protected final Log logger = LogFactory.getLog(getClass()); private ResourceLoader rl = new ResourceLoader("org.theospi.portfolio.presentation.bundle.Messages"); private ServerConfigurationService serverConfigurationService; private EmailService emailService; private UserDirectoryService userDirectoryService; private PresentationShareUserService presentationShareUserService; private UserAgentComparator userAgentComparator = new UserAgentComparator(); private RoleAgentComparator roleAgentComparator = new RoleAgentComparator(); private final String SHAREBY_KEY = "shareBy"; private final String SHAREBY_BROWSE = "share_browse"; private final String SHAREBY_GROUP = "share_group"; private final String SHAREBY_SEARCH = "share_search"; private final String SHAREBY_EMAIL = "share_email"; private final String SHAREBY_ROLE = "share_role"; private final String SHAREBY_ALLROLE= "share_allrole"; /** This accepts email addresses */ protected static final Pattern emailPattern = Pattern.compile( "^" + "(?>" + "\\.?[a-zA-Z\\d!#$%&'*+\\-/=?^_`{|}~]+" + ")+" + "@" + "(" + "(" + "(?!-)[a-zA-Z\\d\\-]+(?<!-)\\." + ")+" + "[a-zA-Z]{2,}" + "|" + "(?!\\.)" + "(" + "\\.?" + "(" + "25[0-5]" + "|" + "2[0-4]\\d" + "|" + "[01]?\\d?\\d" + ")" + "){4}" + ")" + "$" ); public ModelAndView handleRequest(Object requestModel, Map request, Map session, Map application, Errors errors) { // Get specified portfolio/presentation Map model = new HashMap(); boolean returnRedirect = false; Presentation presentation = (Presentation) requestModel; presentation = getPresentationManager().getPresentation(presentation.getId()); model.put("id", presentation.getId().getValue()); // Check if request to return to previous page if ( request.get("back") != null || request.get("back_add") != null ) returnRedirect = true; boolean myWorkspace = getSiteService().isUserSite(presentation.getSiteId()); model.put("presentation", presentation); model.put("hasGroups", getHasGroups(presentation.getSiteId())); model.put("myWorkspace", myWorkspace); model.put("guestEnabled", getGuestUserEnabled()); model.put("baseUrl", PresentationService.VIEW_PRESENTATION_URL); String shareBy = (String)request.get(SHAREBY_KEY); if ( shareBy==null || shareBy.equals("") ) shareBy = myWorkspace ? SHAREBY_SEARCH : SHAREBY_BROWSE; model.put(SHAREBY_KEY, shareBy); // Update list of Shared-with Users List shareList = getShareList(presentation); boolean isUpdated = false; boolean isShareUser = true; if (shareBy.equals(SHAREBY_EMAIL) || shareBy.equals(SHAREBY_SEARCH) ) { String shareUser = (String)request.get("share_user"); if ( shareUser != null && !shareUser.equals("") ) { String errMsg = addUserByEmailOrId(presentation, shareBy, shareUser, shareList); if ( errMsg != null ) { model.put("errMsg", rl.getFormattedMessage(errMsg, new Object[]{shareUser}) ); returnRedirect = false; } } } else if ( shareBy.equals(SHAREBY_BROWSE) || shareBy.equals(SHAREBY_GROUP) ) { List groupList = null; if ( shareBy.equals(SHAREBY_GROUP) ) { groupList = getGroupList(presentation.getSiteId(), request); if ( ! returnRedirect ) model.put("groupList", groupList ); } List availList = getAvailableUserList(presentation.getSiteId(), shareList, groupList); updateAvailList( shareBy, request, presentation, shareList, availList ); if ( ! returnRedirect ) model.put("availList", availList ); } else if ( shareBy.equals(SHAREBY_ROLE) || shareBy.equals(SHAREBY_ALLROLE) ) { List availList = getAvailableRoleList(shareBy, presentation.getSiteId(), shareList); updateAvailList( shareBy, request, presentation, shareList, availList ); if ( ! returnRedirect ) model.put("availList", availList ); } // Check if request to return to previous page // Note: if next view is a redirect, do _not_ include large lists in model if ( returnRedirect ) return new ModelAndView("back", model); else return new ModelAndView("share", model); } /** ** Add specified user (or guest-user/email-address) to the shareList ** ** @param shareBy indicates whether user or email-address is specified ** @param shareUser user to share with (userId or email-address) ** @param shareList current list of shared users ** @return null if successful, otherwise an error message property is returned ** **/ private String addUserByEmailOrId( Presentation presentation, String shareBy, String shareUser, List shareList ) { List userList = getAgentManager().findByProperty(AgentManager.TYPE_EID, shareUser); if(userList == null && shareBy.equals(SHAREBY_EMAIL)){ userList = getAgentManager().findByProperty(AgentManager.TYPE_EMAIL, shareUser); } // Check if user not found (and not share-by-email or guest user) if ( userList==null && shareBy.equals(SHAREBY_SEARCH) ) { return "share_err_user"; } // Otherwise if user not found and this is share-by-email or guest user (assume SHAREBY_EMAIL) else if ( userList == null ) { if ( validateEmail(shareUser) ) { Agent agent = getAgentManager().createAgent(shareUser, getIdManager().getId(shareUser) ); if (agent != null) { notifyNewUserEmail( agent ); shareList.add( agent ); } else { return "share_err_email"; } } else { return "share_err_email"; } } // Check for duplciates else if ( isUserShared( (Agent)userList.get(0), shareList) ) { return "share_err_dup"; } // Otherwise, user is found; add to the shareList else { Agent agent = (Agent) userList.get(0); shareList.add(agent); presentationShareUserService.triggerAddUserEvent(presentation.getId().getValue(), // add to cluster agent.getId().getValue()); } return null; } /** Check if given user is already in shareList **/ private boolean isUserShared( Agent agent, List shareList ) { for (Iterator it = shareList.iterator(); it.hasNext();) { Agent shareUser = (Agent) it.next(); if ( shareUser.getId().getValue().equals( agent.getId().getValue() ) ) return true; } return false; } /** ** Verify syntax of email adddress and verify it does not ** contain the invalidEmailInIdAccountString string from sakai.properties ** ** @param email email address string ** @return boolean true if valid, otherwise false **/ protected boolean validateEmail(String email) { if (!emailPattern.matcher(email).matches()) return false; String invalidEmailInIdAccountString = getServerConfigurationService().getString("invalidEmailInIdAccountString", null); if(invalidEmailInIdAccountString != null) { String[] invalidDomains = invalidEmailInIdAccountString.split(","); for(int i = 0; i < invalidDomains.length; i++) { String domain = invalidDomains[i].trim(); if(email.toLowerCase().indexOf(domain.toLowerCase()) != -1) { return false; } } } return true; } /** ** Notify specified guest user that they have been added as a guest user ** TBD: change to use email template service **/ private void notifyNewUserEmail(Agent guest) { String from = getServerConfigurationService().getString("setup.request", null); if (from == null) { from = "postmaster@".concat(getServerConfigurationService().getServerName()); } String productionSiteName = getServerConfigurationService().getString("ui.service", ""); String productionSiteUrl = getServerConfigurationService().getPortalUrl(); String to = guest.getDisplayName(); String headerTo = to; String replyTo = to; String message_subject = rl.getFormattedMessage("email.guestusernoti", new Object[]{productionSiteName}); String content = ""; if (from != null && to != null) { StringBuilder buf = new StringBuilder(); buf.setLength(0); // email body buf.append(to + ":\n\n"); buf.append(rl.getFormattedMessage("email.addedto", new Object[]{productionSiteName, productionSiteUrl}) + "\n\n"); buf.append(rl.getFormattedMessage("email.simpleby", new Object[]{getUserDirectoryService().getCurrentUser().getDisplayName()}) + "\n\n"); buf.append(rl.getFormattedMessage("email.userid", new Object[]{to}) + "\n\n"); buf.append(rl.getFormattedMessage("email.password", new Object[]{guest.getPassword()}) + "\n\n"); content = buf.toString(); getEmailService().send(from, to, message_subject, content, headerTo, replyTo, null); } } /** ** get session-based share list **/ private List getShareList( Presentation presentation ) { List shareList = presentationShareUserService.getSharedList(presentation); return shareList; } /** ** set session-based share list **/ private void setShareList( Presentation presentation, List shareList ) { presentationShareUserService.setSharedList(shareList, presentation); } /** ** Check if adding user by email is enabled/disabled **/ private Boolean getGuestUserEnabled() { if ( getServerConfigurationService().getBoolean("notifyNewUserEmail",true) ) return Boolean.valueOf(true); else return Boolean.valueOf(false); } /** ** Check for share list changes from form submission and update shareList and availList if necessary ** ** @return true if update was necessary, otherwise false **/ private boolean updateAvailList( String shareBy, Map request, Presentation presentation, List shareList, List availList ) { boolean mods = false; ArrayList selectedList = new ArrayList(); ArrayList newAvailList = new ArrayList(); if (shareBy.equals(SHAREBY_BROWSE) || shareBy.equals(SHAREBY_GROUP)) { for (Iterator it = availList.iterator(); it.hasNext();) { Agent availItem = (Agent) it.next(); if ( request.get(availItem.getId().getValue()) != null ) { mods = true; // selectedList.add( availItem ); presentationShareUserService.triggerAddUserEvent(presentation.getId().getValue(), // add user to the cluster's cache availItem.getId().getValue()); } else { newAvailList.add( availItem ); } } } else // (shareBy.equals(SHAREBY_ROLE) || shareBy.equals(SHAREBY_ALLROLE)) { for (Iterator it = availList.iterator(); it.hasNext();) { AgentWrapper availItem = (AgentWrapper) it.next(); if ( request.get(availItem.getId().getValue()) != null ) { mods = true; // selectedList.add( availItem ); presentationShareUserService.triggerAddUserEvent(presentation.getId().getValue(), // add user to the cluster's cache availItem.getId().getValue()); } else { newAvailList.add( availItem ); } } } if ( mods ) { // Add selected items to shareList and save // shareList.addAll(selectedList); // setShareList(presentation, shareList); // Delete selected items from availList availList.clear(); availList.addAll(newAvailList); } return mods; } /** Return list of available users (i.e. not in shareList) optionally filtered by group **/ private List getAvailableUserList( String siteId, List shareList, List groupList ) { ArrayList availableUserList = new ArrayList(); ArrayList userMemberList = new ArrayList(); userMemberList.addAll(getFilteredMembersList(siteId, groupList)); for (Iterator it1 = userMemberList.iterator(); it1.hasNext();) { Agent availableItem = (Agent)it1.next(); boolean matchFound = false; for (Iterator it2 = shareList.iterator(); it2.hasNext();) { Agent selectedItem = (Agent) it2.next(); if (selectedItem.getId().getValue().equals(availableItem.getId().getValue())) { matchFound = true; break; } } if (!matchFound){ availableUserList.add(availableItem); } } Collections.sort(availableUserList, userAgentComparator); return availableUserList; } /* Return list of available roles */ private List getAvailableRoleList( String shareBy, String siteId, List shareList ) { ArrayList availableRoleList = new ArrayList(); ArrayList roleMemberList = new ArrayList(); if ( shareBy.equals(SHAREBY_ROLE) ) roleMemberList.addAll(getRoles(siteId)); else // (shareBy.equals(SHAREBY_ALLROLE) roleMemberList.addAll(getRoles(null)); for (Iterator it1 = roleMemberList.iterator(); it1.hasNext();) { AgentWrapper availableItem = (AgentWrapper)it1.next(); boolean matchFound = false; for (Iterator it2 = shareList.iterator(); it2.hasNext();) { Agent selectedItem = (Agent) it2.next(); if (selectedItem.getId().getValue().equals(availableItem.getId().getValue())) { matchFound = true; break; } } if (!matchFound){ availableRoleList.add(availableItem); } } Collections.sort(availableRoleList, roleAgentComparator); return availableRoleList; } /** ** Return list of roles for this or all worksites **/ public List getRoles( String siteId ) { List roleList = new ArrayList(); // get roles for specified sites if ( siteId != null ) { Site site = null; Set roles = null; try { site = getSiteService().getSite(siteId); roles = site.getRoles(); } catch (Exception e) { logger.warn(e.toString()); return roleList; } for (Iterator i = roles.iterator(); i.hasNext();) { Role role = (Role) i.next(); Agent agent = getAgentManager().getWorksiteRole(role.getId(), site.getId()); AgentWrapper roleAgent = new AgentWrapper( agent, site.getTitle() ); roleList.add(roleAgent); } } // get all site roles (no site has been specified) else { List siteList = getSiteService().getSites(SiteService.SelectionType.ACCESS, null, null, null, SiteService.SortType.TITLE_ASC, null); for (Iterator siteIt = siteList.iterator(); siteIt.hasNext();) { Site site = (Site)siteIt.next(); Set roles = site.getRoles(); for (Iterator roleIt = roles.iterator(); roleIt.hasNext();) { Role role = (Role) roleIt.next(); Agent agent = getAgentManager().getWorksiteRole(role.getId(), site.getId()); AgentWrapper roleAgent = new AgentWrapper( agent, site.getTitle() ); roleList.add(roleAgent); } } } return roleList; } /** Spring Injection Methods **/ public ServerConfigurationService getServerConfigurationService() { return serverConfigurationService; } public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } public EmailService getEmailService() { return emailService; } public void setEmailService( EmailService emailService ) { this.emailService = emailService; } public UserDirectoryService getUserDirectoryService() { return userDirectoryService; } public void setUserDirectoryService( UserDirectoryService userDirectoryService) { this.userDirectoryService = userDirectoryService; } public PresentationShareUserService getPresentationShareUserService() { return presentationShareUserService; } public void setPresentationShareUserService(PresentationShareUserService presentationShareUserService) { this.presentationShareUserService = presentationShareUserService; } /** Comparator for sorting role-based AgentWrapper objects **/ public class RoleAgentComparator implements Comparator<AgentWrapper> { public int compare(AgentWrapper o1, AgentWrapper o2) { return o1.getDisplayName().compareTo( o2.getDisplayName() ); } } }