From fcadd299aeedc6888dfc14aad07360db4663524a Mon Sep 17 00:00:00 2001 From: danielmerino Date: Thu, 26 Mar 2015 14:40:29 +0100 Subject: [PATCH] SAK-11647 - Group-aware dropboxes. New permission dropbox.maintain.own.groups added. Notifications extended to group TAs. Several fixes to corrections of Matthew Buckett. --- .../content/tool/ResourcesAction.java | 35 ++++++++++++++- .../SiteEmailNotificationDragAndDrop.java | 28 ++++++++++++ .../webapp/vm/content/sakai_resources_list.vm | 2 + .../content/api/ContentHostingService.java | 10 +++++ .../content/cover/ContentHostingService.java | 9 ++++ .../content/impl/BaseContentService.java | 43 +++++++++++++++++-- 6 files changed, 123 insertions(+), 4 deletions(-) diff --git a/content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java b/content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java index 62ee734c3470..2eeb6dfd4e33 100644 --- a/content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java +++ b/content/content-tool/tool/src/java/org/sakaiproject/content/tool/ResourcesAction.java @@ -4215,7 +4215,6 @@ public String buildListContext ( VelocityPortlet portlet, // notshow the public option or notification when in dropbox mode context.put("dropboxMode", Boolean.TRUE); // allow filtering of dropboxes by group (SAK-14625) - String collectionId = (String) state.getAttribute (STATE_COLLECTION_ID); String homeCollectionId = (String) state.getAttribute(STATE_HOME_COLLECTION_ID); String containingCollectionId = ContentHostingService.getContainingCollectionId(homeCollectionId); //Boolean showDropboxGroupFilter = Boolean.valueOf(homeCollectionId.equals(collectionId)); @@ -4250,6 +4249,40 @@ public int compare(Group g0, Group g1) { // something failed, group filter will be hidden } } + + //SAK-11647 - Group-aware dropboxes + try + { + String currentUser = SessionManager.getCurrentSessionUserId(); + Site site = SiteService.getSite(currentSiteId); + + if ((!ContentHostingService.isDropboxMaintainer(currentSiteId))&&(ContentHostingService.isDropboxGroups(currentSiteId))) + { + context.put("dropboxGroupPermission_enabled",Boolean.TRUE); + + List site_groups = new ArrayList(); + + Set allGroupsUsers = new TreeSet(); + + site_groups.addAll(site.getGroupsWithMember(currentUser)); + if (site_groups.size()>0) + { + for (Group g : site_groups) + { + allGroupsUsers.addAll(g.getUsers()); + } + } + context.put("dropboxGroupPermission_allGroupsUsers",allGroupsUsers); + } + else + { + context.put("dropboxGroupPermission_enabled",Boolean.FALSE); + } + } + catch (IdUnusedException e) + { + logger.warn("DropboxGroupPermission error: "+e.toString()); + } } else { diff --git a/content/content-tool/tool/src/java/org/sakaiproject/content/tool/SiteEmailNotificationDragAndDrop.java b/content/content-tool/tool/src/java/org/sakaiproject/content/tool/SiteEmailNotificationDragAndDrop.java index 4ee78c70ea61..15d39abbba3c 100644 --- a/content/content-tool/tool/src/java/org/sakaiproject/content/tool/SiteEmailNotificationDragAndDrop.java +++ b/content/content-tool/tool/src/java/org/sakaiproject/content/tool/SiteEmailNotificationDragAndDrop.java @@ -28,6 +28,7 @@ import org.sakaiproject.event.api.Notification; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.Group; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.authz.api.Member; import org.sakaiproject.exception.IdUnusedException; @@ -226,6 +227,12 @@ protected List getRecipients(Event event) String siteDropbox = buf.toString(); recipients.addAll(securityService.unlockUsers(contentHostingService.AUTH_DROPBOX_MAINTAIN, siteDropbox)); + + //SAK-11647 - Adding to notifications all users with AUTH_DROPBOX_GROUPS who belong to current user's groups. + List dropboxGroupsRecipients = new ArrayList(); + dropboxGroupsRecipients.addAll(securityService.unlockUsers(contentHostingService.AUTH_DROPBOX_GROUPS, siteDropbox)); + recipients.addAll(filterUsersInGroups(dropboxGroupsRecipients, modifiedBy, site)); + refineToSiteMembers(recipients, site); } else @@ -259,6 +266,27 @@ protected List getRecipients(Event event) return super.getRecipients(event); } } + + private List filterUsersInGroups(List usersToFilter, String currentUser, Site site) + { + List usersInCurrentUserGroups = new ArrayList(); + List site_groups = new ArrayList(); + List allGroupsUsers = new ArrayList(); + + site_groups.addAll(site.getGroupsWithMember(currentUser)); + if (site_groups.size()>0) + { + for (Group g : site_groups) + { + allGroupsUsers.addAll(g.getUsers()); + } + } + for (User user : usersToFilter) + { + if (allGroupsUsers.contains(user.getId())) usersInCurrentUserGroups.add(user); + } + return usersInCurrentUserGroups; + } /** * Only include actual site members in the notification. diff --git a/content/content-tool/tool/src/webapp/vm/content/sakai_resources_list.vm b/content/content-tool/tool/src/webapp/vm/content/sakai_resources_list.vm index 76eed49a7924..b9f7dc2107fe 100644 --- a/content/content-tool/tool/src/webapp/vm/content/sakai_resources_list.vm +++ b/content/content-tool/tool/src/webapp/vm/content/sakai_resources_list.vm @@ -309,6 +309,7 @@ if ( window.jQuery ) { #foreach($item in $site) #set($qid=$item.id.replaceAll("'","\\'").replaceAll("\"", """)) #set($dqid=$item.id.replaceAll("\"", """)) + #if ((!$dropboxGroupPermission_enabled) || ($item.isDropbox() && $item.DropboxOwner && $dropboxGroupPermission_allGroupsUsers.contains($item.DropboxOwner))) #if(!$dropboxGroupFiltered || ($item.isDropbox() && $dropboxGroupFilter_groupUsers.contains($item.DropboxOwner)) ) #set($itemcount = $itemcount + 1) #set ($addCount=($addCount - 1)) @@ -491,6 +492,7 @@ if ( window.jQuery ) { #end #end ## if !$dropboxGroupFiltered || ($item.isDropbox() && $dropboxGroupFilter_groupUsers.contains($item.DropboxOwner)) + #end ##if ((!$dropboxGroupPermission_enabled) || ($item.isDropbox() && $item.DropboxOwner && $dropboxGroupPermission_allGroupsUsers.contains($item.DropboxOwner))) #end ## foreach $item in $this_site ############################################# Begin "Other sites" section diff --git a/kernel/api/src/main/java/org/sakaiproject/content/api/ContentHostingService.java b/kernel/api/src/main/java/org/sakaiproject/content/api/ContentHostingService.java index 9ef2d2c32e6e..ba7f83493cb3 100644 --- a/kernel/api/src/main/java/org/sakaiproject/content/api/ContentHostingService.java +++ b/kernel/api/src/main/java/org/sakaiproject/content/api/ContentHostingService.java @@ -168,6 +168,9 @@ public interface ContentHostingService extends EntityProducer /** Security function for those who may OWN a dropbox. */ public static final String AUTH_DROPBOX_OWN = "dropbox.own"; + + /** Security function for those who may maintain dropboxes of their groups/sections. */ + public static final String AUTH_DROPBOX_GROUPS = "dropbox.maintain.own.groups"; /** Security function for those who may maintain dropboxes. */ public static final String AUTH_DROPBOX_MAINTAIN = "dropbox.maintain"; @@ -1715,6 +1718,13 @@ public ResourceProperties removeProperty(String id, String name) throws Permissi */ public boolean isDropboxMaintainer(String siteId); + /** + * Determine whether the user has the dropbox.groups permission + * + * @return True if user has dropbox.groups permission, false otherwise. + */ + public boolean isDropboxGroups(String siteId); + /** * Access the default dropbox collection display name for the current request. If the current user has permission to modify the site's dropbox collection, this is returned. Otherwise, the current user's collection within the site's dropbox is * returned. diff --git a/kernel/api/src/main/java/org/sakaiproject/content/cover/ContentHostingService.java b/kernel/api/src/main/java/org/sakaiproject/content/cover/ContentHostingService.java index a41a3fb72acd..5637b756612c 100644 --- a/kernel/api/src/main/java/org/sakaiproject/content/cover/ContentHostingService.java +++ b/kernel/api/src/main/java/org/sakaiproject/content/cover/ContentHostingService.java @@ -99,6 +99,7 @@ public static org.sakaiproject.content.api.ContentHostingService getInstance() public static java.lang.String AUTH_GROUP_RESOURCE_READ = org.sakaiproject.content.api.ContentHostingService.AUTH_GROUP_RESOURCE_READ; public static java.lang.String AUTH_RESOURCE_HIDDEN = org.sakaiproject.content.api.ContentHostingService.AUTH_RESOURCE_HIDDEN; public static java.lang.String AUTH_DROPBOX_OWN = org.sakaiproject.content.api.ContentHostingService.AUTH_DROPBOX_OWN; + public static java.lang.String AUTH_DROPBOX_GROUPS = org.sakaiproject.content.api.ContentHostingService.AUTH_DROPBOX_GROUPS; public static java.lang.String AUTH_DROPBOX_MAINTAIN = org.sakaiproject.content.api.ContentHostingService.AUTH_DROPBOX_MAINTAIN; public static java.lang.String PROP_ALTERNATE_REFERENCE = org.sakaiproject.content.api.ContentHostingService.PROP_ALTERNATE_REFERENCE; @@ -923,6 +924,14 @@ public static boolean isDropboxMaintainer(java.lang.String param0) return service.isDropboxMaintainer(param0); } + public static boolean isDropboxGroups(java.lang.String param0) + { + org.sakaiproject.content.api.ContentHostingService service = getInstance(); + if (service == null) return false; + + return service.isDropboxGroups(param0); + } + public static java.lang.String getDropboxDisplayName() { org.sakaiproject.content.api.ContentHostingService service = getInstance(); diff --git a/kernel/kernel-impl/src/main/java/org/sakaiproject/content/impl/BaseContentService.java b/kernel/kernel-impl/src/main/java/org/sakaiproject/content/impl/BaseContentService.java index 95cff0d86be0..b42f872e509d 100644 --- a/kernel/kernel-impl/src/main/java/org/sakaiproject/content/impl/BaseContentService.java +++ b/kernel/kernel-impl/src/main/java/org/sakaiproject/content/impl/BaseContentService.java @@ -952,6 +952,7 @@ public void init() functionManager.registerFunction(AUTH_RESOURCE_HIDDEN, true); functionManager.registerFunction(AUTH_DROPBOX_OWN, false); + functionManager.registerFunction(AUTH_DROPBOX_GROUPS, false); functionManager.registerFunction(AUTH_DROPBOX_MAINTAIN, false); // quotas @@ -1491,13 +1492,27 @@ protected String convertLockIfDropbox(String lock, String id) } // if this resource is a dropbox, you need dropbox maintain permission + // Changed in SAK-11647 to enable group-aware dropboxes if (id.startsWith(COLLECTION_DROPBOX)) { // only for /group-user/SITEID/USERID/ refs. String[] parts = StringUtil.split(id, "/"); if (parts.length >= 3) { - return AUTH_DROPBOX_MAINTAIN; + String ref = null; + if (id != null) + { + ref = getReference(id); + } + + //Before SAK-11647 any dropbox id asked for dropbox.maintain permission. + //Now we must support groups permission, so we ask for this permission too. + //Groups permission gives full access to dropboxes of users in current user's groups. + //A different logic can be achieved here depending of lock parameter received. + if (m_securityService.unlock(AUTH_DROPBOX_MAINTAIN, ref)) + return AUTH_DROPBOX_MAINTAIN; + else if (m_securityService.unlock(AUTH_DROPBOX_GROUPS, ref)) + return AUTH_DROPBOX_GROUPS; } } @@ -1703,6 +1718,7 @@ protected boolean unlockCheck(String lock, String id) boolean isAllowed = m_securityService.isSuperUser(); if(! isAllowed) { + //SAK-11647 - Changes in this function. lock = convertLockIfDropbox(lock, id); // make a reference from the resource id, if specified @@ -1766,6 +1782,7 @@ protected void unlock(String lock, String id) throws PermissionException return; } + //SAK-11647 - Changes in this function. lock = convertLockIfDropbox(lock, id); // make a reference from the resource id, if specified @@ -9823,8 +9840,8 @@ public String getDropboxCollection(String siteId) // form the site's dropbox collection rv = COLLECTION_DROPBOX + siteId + "/"; - // for maintainers, use the site level - if (isDropboxMaintainer(siteId)) + // for maintainers or users with groups access, use the site level + if ((isDropboxMaintainer(siteId))||(isDropboxGroups(siteId))) { // return the site's dropbox collection return rv; @@ -10154,6 +10171,26 @@ public boolean isDropboxMaintainer(String siteId) return m_securityService.unlock(AUTH_DROPBOX_MAINTAIN, m_siteService.siteReference(siteId)); } + /** + * Determine whether the user has the dropbox.groups permission + * + * @return True if user has dropbox.groups permission, false otherwise. + */ + public boolean isDropboxGroups(String siteId) + { + String dropboxId = null; + + // make sure we are in a worksite, not a workspace + if (m_siteService.isUserSite(siteId) || m_siteService.isSpecialSite(siteId)) + { + return false; + } + + // if the user has dropbox maintain in the site, they are the dropbox maintainer + // (dropbox maintain in their myWorkspace just gives them access to their own dropbox) + return m_securityService.unlock(AUTH_DROPBOX_GROUPS, m_siteService.siteReference(siteId)); + } + /****************************************************************************************************************************************************************************************************************************************************** * Group awareness implementation *****************************************************************************************************************************************************************************************************************************************************/