/** * $Id: SiteEntityProvider.java 132825 2013-12-19 21:22:20Z csev@umich.edu $ * $URL: https://source.sakaiproject.org/svn/entitybroker/trunk/core-providers/src/java/org/sakaiproject/entitybroker/providers/SiteEntityProvider.java $ * SiteEntityProvider.java - entity-broker - Jun 29, 2008 8:35:55 AM - azeckoski ************************************************************************** * 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.sakaiproject.entitybroker.providers; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Properties; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.azeckoski.reflectutils.ReflectUtils; import org.sakaiproject.authz.api.AuthzGroup; import org.sakaiproject.authz.api.AuthzGroupService; import org.sakaiproject.authz.api.AuthzPermissionException; import org.sakaiproject.authz.api.FunctionManager; import org.sakaiproject.authz.api.GroupNotDefinedException; import org.sakaiproject.authz.api.Member; import org.sakaiproject.authz.api.Role; import org.sakaiproject.authz.api.RoleAlreadyDefinedException; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.entity.api.ResourceProperties; import org.sakaiproject.entity.api.ResourcePropertiesEdit; import org.sakaiproject.entitybroker.EntityReference; import org.sakaiproject.entitybroker.EntityView; import org.sakaiproject.entitybroker.EntityView.Method; import org.sakaiproject.entitybroker.entityprovider.CoreEntityProvider; import org.sakaiproject.entitybroker.entityprovider.annotations.EntityCustomAction; import org.sakaiproject.entitybroker.entityprovider.annotations.EntityParameters; import org.sakaiproject.entitybroker.entityprovider.annotations.EntityURLRedirect; import org.sakaiproject.entitybroker.entityprovider.capabilities.ActionsExecutable; import org.sakaiproject.entitybroker.entityprovider.capabilities.DepthLimitable; import org.sakaiproject.entitybroker.entityprovider.capabilities.RESTful; import org.sakaiproject.entitybroker.entityprovider.capabilities.Redirectable; import org.sakaiproject.entitybroker.entityprovider.capabilities.RequestStorable; import org.sakaiproject.entitybroker.entityprovider.extension.ActionReturn; import org.sakaiproject.entitybroker.entityprovider.extension.Formats; import org.sakaiproject.entitybroker.entityprovider.extension.RequestStorage; import org.sakaiproject.entitybroker.entityprovider.search.Restriction; import org.sakaiproject.entitybroker.entityprovider.search.Search; import org.sakaiproject.entitybroker.providers.model.EntityGroup; import org.sakaiproject.entitybroker.providers.model.EntitySite; import org.sakaiproject.entitybroker.util.AbstractEntityProvider; import org.sakaiproject.entitybroker.util.TemplateParseUtil; import org.sakaiproject.exception.IdInvalidException; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.IdUsedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.javax.PagingPosition; import org.sakaiproject.site.api.Group; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SitePage; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.api.ToolConfiguration; import org.sakaiproject.site.api.SiteService.SelectionType; import org.sakaiproject.site.api.SiteService.SortType; import org.sakaiproject.thread_local.cover.ThreadLocalManager; import org.sakaiproject.tool.api.Tool; import org.sakaiproject.util.FormattedText; /** * Creates a provider for dealing with sites * * @author Aaron Zeckoski (azeckoski @ gmail.com) */ public class SiteEntityProvider extends AbstractEntityProvider implements CoreEntityProvider, RESTful, ActionsExecutable, Redirectable, RequestStorable, DepthLimitable { private int maxDepth = 7; public void setMaxDepth(int maxDepth) { this.maxDepth = maxDepth; } public int getMaxDepth() { return maxDepth; } private static Log log = LogFactory.getLog(SiteEntityProvider.class); private SiteService siteService; public void setSiteService(SiteService siteService) { this.siteService = siteService; } private AuthzGroupService authzGroupService; public void setAuthzGroupService(AuthzGroupService authzGroupService) { this.authzGroupService = authzGroupService; } private FunctionManager functionManager; public void setFunctionManager(FunctionManager functionManager) { this.functionManager = functionManager; } private UserEntityProvider userEntityProvider; public void setUserEntityProvider(UserEntityProvider userEntityProvider) { this.userEntityProvider = userEntityProvider; } private ServerConfigurationService serverConfigurationService; public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } private SecurityService securityService; public void setSecurityService(SecurityService securityService) { this.securityService = securityService; } public static String PREFIX = "site"; public String getEntityPrefix() { return PREFIX; } private static final String GROUP_PROP_WSETUP_CREATED = "group_prop_wsetup_created"; /** Property to set the default page size for lists of entities. */ public static final String PROP_SITE_PROVIDER_PAGESIZE_DEFAULT = "site.entity.pagesize.default"; /** Property to set the maximum page size for lists of entities. */ public static final String PROP_SITE_PROVIDER_PAGESIZE_MAXIMUM = "site.entity.pagesize.maximum"; /** * The default page size for lists of entities. May be overridden with * a property of "site.entity.pagesize.default". */ private int defaultPageSize = 50; /** * The maximum page size for lists of entities. May be overridden with * a property of "site.entity.pagesize.maximum". */ private int maxPageSize = 500; public void init() { int dps = serverConfigurationService.getInt( PROP_SITE_PROVIDER_PAGESIZE_DEFAULT, defaultPageSize); if (dps > 0) { defaultPageSize = dps; } int mps = serverConfigurationService.getInt( PROP_SITE_PROVIDER_PAGESIZE_MAXIMUM, maxPageSize); if (mps >= defaultPageSize) { maxPageSize = mps; } else { maxPageSize = defaultPageSize; } } // ACTIONS @EntityURLRedirect("/{prefix}/{id}/memberships") public String redirectMemberships(Map<String, String> vars) { return MembershipEntityProvider.PREFIX + "/site/" + vars.get("id") + vars.get(TemplateParseUtil.DOT_EXTENSION); } @EntityCustomAction(action = "exists", viewKey = EntityView.VIEW_SHOW) public boolean checkSiteExists(EntityView view) { String siteId = view.getEntityReference().getId(); boolean exists = entityExists(siteId); return exists; } @EntityCustomAction(action = "role", viewKey = "") public void handleRoles(EntityView view) { String siteId = view.getEntityReference().getId(); String roleId = view.getPathSegment(3); if (roleId == null) { throw new IllegalArgumentException("No role id specified"); } Site site = getSiteById(siteId); if (view.getMethod().equals(Method.POST.name())) { try { site.addRole(roleId); } catch (RoleAlreadyDefinedException e) { // Ignore } } else if (view.getMethod().equals(Method.DELETE.name())) { site.removeRole(roleId); } else { throw new IllegalArgumentException("Method " + view.getMethod() + " not supported"); } try { siteService.save(site); } catch (IdUnusedException e) { // Ignore } catch (PermissionException e) { throw new SecurityException("User not allowed to update role " + roleId + " in site " + siteId); } } @EntityCustomAction(action = "perms", viewKey = EntityView.VIEW_SHOW) public Map<String, Set<String>> handlePerms(EntityView view) { // expects site/siteId/perms[/:PREFIX:] String prefix = view.getPathSegment(3); String userId = developerHelperService.getCurrentUserId(); if (userId == null) { throw new SecurityException( "This action (perms) is not accessible to anon and there is no current user."); } String siteId = view.getEntityReference().getId(); Site site = getSiteById(siteId); Set<Role> roles = site.getRoles(); Map<String, Set<String>> perms = new HashMap<String, Set<String>>(); for (Role role : roles) { Set<String> functions = role.getAllowedFunctions(); Set<String> filteredFunctions = new TreeSet<String>(); if (prefix != null) { for (String function : functions) { if (function.startsWith(prefix)) { filteredFunctions.add(function); } } } else { filteredFunctions = functions; } perms.put(role.getId(), filteredFunctions); } return perms; } @EntityCustomAction(action="setPerms", viewKey=EntityView.VIEW_EDIT) public String handleSetPerms(EntityReference ref, Map<String, Object> params) { String userId = developerHelperService.getCurrentUserId(); if (userId == null) { throw new SecurityException( "This action (setPerms) is not accessible to anon and there is no current user."); } String siteId = ref.getId(); Site site = getSiteById(siteId); List<String> userMutableFunctions = functionManager.getRegisteredUserMutableFunctions(); boolean admin = developerHelperService.isUserAdmin(developerHelperService .getCurrentUserReference()); try { AuthzGroup authzGroup = authzGroupService.getAuthzGroup(site.getReference()); boolean changed = false; for (String name : params.keySet()) { if (!name.contains(":")) { continue; } String value = (String) params.get(name); String roleId = name.substring(0, name.indexOf(":")); Role role = authzGroup.getRole(roleId); if (role == null) { throw new IllegalArgumentException("Invalid role id '" + roleId + "' provided in POST parameters."); } String function = name.substring(name.indexOf(":") + 1); // Only change this function if registered as userMutable if (admin || userMutableFunctions.contains(function)) { if ("true".equals(value)) { role.allowFunction(function); } else { role.disallowFunction(function); } } else { throw new SecurityException("The function " + function + " cannot be updated by the current user."); } changed = true; } if (changed) { try { authzGroupService.save(authzGroup); } catch (AuthzPermissionException ape) { throw new SecurityException("The permissions for this site (" + siteId + ") cannot be updated by the current user."); } } } catch (GroupNotDefinedException gnde) { throw new IllegalArgumentException("No realm defined for site (" + siteId + ")."); } return "SUCCESS"; } @EntityCustomAction(action = "group", viewKey = "") public EntityGroup handleGroups(EntityView view, Map<String, Object> params) { // expects site/siteId/group/groupId String siteId = view.getEntityReference().getId(); String groupId = view.getPathSegment(3); EntityGroup eg = null; String groupTitle = params.containsKey("groupTitle") ? params.get("groupTitle").toString() : null; String groupDescription = params.get("groupDescription") != null ? params.get("groupDescription").toString() : null; // fix empty strings that may be specified if ("".equals(groupTitle)) { groupTitle = null; } if ("".equals(groupDescription)) { groupDescription = null; } List<String> userIds = params.get("userIds") != null ? Arrays.asList(params.get("userIds") .toString().split(",")) : new ArrayList<String>(); Site site = getSiteById(siteId); // check if the user can access site isAllowedAccessSite(site); // check if the user can update group membership if (!siteService.allowUpdateGroupMembership(site.getId())) { throw new SecurityException("This group (" + groupId + ") in site (" + siteId + ") cannot be updated by the current user."); } Group group = null; if (EntityView.Method.GET.name().equals(view.getMethod())) { // GET /direct/site/siteid/group/groupid if (groupId == null) { throw new IllegalArgumentException("Invalid path provided: expected to receive the groupId"); } group = site.getGroup(groupId); eg = new EntityGroup(group); return eg; } else if (EntityView.Method.PUT.name().equals(view.getMethod())) { // PUT /direct/site/siteid/group - create a new group in the site (returns group id). // Params include title, description, optionally initial list of members if (groupTitle == null) { // No title metadata specified throw new IllegalArgumentException("A title needs to be provided for a new group."); } group = site.addGroup(); group.getProperties().addProperty(GROUP_PROP_WSETUP_CREATED, Boolean.TRUE.toString()); group.setTitle(groupTitle); group.setDescription(groupDescription); // add new members for (String userId : userIds) { // Every user added via this EB is defined as non-provided Role role = site.getUserRole(userId); Member m = site.getMember(userId); if (group.getUserRole(userId) == null && role != null) { group.addMember(userId, role.getId(), m != null ? m.isActive() : true, false); } } try { siteService.save(site); } catch (IdUnusedException e) { throw new IllegalArgumentException("Cannot find site with given id: " + siteId + ":" + e.getMessage(), e); } catch (PermissionException e) { throw new SecurityException( "Current user does not have permission to add a group to site:" + siteId); } } else if (EntityView.Method.POST.name().equals(view.getMethod())) { // POST /direct/site/siteid/group/groupid - update metadata for group but not membership if (groupTitle == null) { // No metadata specified throw new IllegalArgumentException("A group title needs to be provided to edit group: " + groupId); } group = site.getGroup(groupId); if (group != null) { checkGroupType(group); if (groupTitle != null) { group.setTitle(groupTitle); } //clear description if it is not provided if (groupDescription != null) { groupDescription = groupDescription.trim(); } group.setDescription(groupDescription); } else { throw new IllegalArgumentException("Cannot find a group with given id: " + groupId + " in site:" + siteId); } try { siteService.save(site); } catch (IdUnusedException e) { throw new IllegalArgumentException("Cannot find site with given id: " + siteId + ":" + e.getMessage(), e); } catch (PermissionException e) { throw new SecurityException("This group: " + groupId + " cannot be edited by the current user."); } } else if (EntityView.Method.DELETE.name().equals(view.getMethod())) { // DELETE /direct/site/siteid/group - delete an existing group in the site. if (groupId == null) { throw new IllegalArgumentException( "Invalid path provided: expect to receive the groupId"); } group = site.getGroup(groupId); checkGroupType(group); site.removeGroup(group); try { siteService.save(site); } catch (IdUnusedException e) { throw new IllegalArgumentException("Cannot find site with given id: " + siteId + ":" + e.getMessage(), e); } catch (PermissionException e) { throw new SecurityException("This group: " + groupId + " cannot be deleted by the current user."); } return null; } eg = new EntityGroup(group); return eg; } @EntityCustomAction(action = "userPerms", viewKey = EntityView.VIEW_SHOW) public Set<String> handleUserPerms(EntityView view) { // expects site/siteId/userPerms[/:PREFIX:] String prefix = view.getPathSegment(3); String userId = developerHelperService.getCurrentUserId(); if (userId == null) { throw new SecurityException("This action (userPerms) is not accessible to anon and there is no current user."); } String siteId = view.getEntityReference().getId(); String siteReference = siteService.siteReference(siteId); List<String> functions = null; if (prefix != null) { functions = functionManager.getRegisteredFunctions(prefix); } else { functions = functionManager.getRegisteredFunctions(); } Set<String> filteredFunctions = new TreeSet<String>(); for (String function : functions) { if(securityService.unlock(userId,function,siteReference)) { filteredFunctions.add(function); } } return filteredFunctions; } @EntityCustomAction(action = "pages", viewKey = EntityView.VIEW_SHOW) public ActionReturn getPagesAndTools(EntityView view, Search search) { // expects site/siteId/pages String userId = developerHelperService.getCurrentUserId(); if (userId == null) { throw new SecurityException( "This action (pages) is not accessible to anon and there is no current user."); } boolean admin = developerHelperService.isUserAdmin(developerHelperService.getCurrentUserReference()); String siteId = view.getEntityReference().getId(); Site site = getSiteById(siteId); if (! admin) { Member member = site.getMember(userId); if (member == null || ! member.isActive()) { throw new SecurityException("User ("+userId+") cannot access the site pages list for site ("+site.getId()+")"); } //role = member.getRole(); } boolean includeProps = false; boolean includeConfig = false; if (search != null) { Restriction r = search.getRestrictionByProperty("props"); if (r != null && r.getBooleanValue()) { includeProps = true; } Restriction r2 = search.getRestrictionByProperty("config"); if (r2 != null && r2.getBooleanValue()) { includeConfig = true; } } // hardcoding to make this backwards compatible with 2.3 - ServerConfigurationService.CURRENT_PORTAL_PATH, PORTAL_BASE); String portalBase = (String) ThreadLocalManager.get("sakai:request.portal.path"); if (portalBase == null || "".equals(portalBase) || "/sakai-entitybroker-direct".equals(portalBase)) { // this has to be here because the tc will expect it when the portal urls are generated and fail if it is missing -AZ ThreadLocalManager.set("sakai:request.portal.path", "/portal"); } // get the pages for this site List<Map<String, Object>> data = new ArrayList<Map<String,Object>>(); List<SitePage> pages = site.getOrderedPages(); for (SitePage page : pages) { HashMap<String, Object> pageData = new HashMap<String, Object>(); pageData.put("id", page.getId()); pageData.put("layoutTitle", page.getLayoutTitle()); pageData.put("layout", page.getLayout()); pageData.put("position", page.getPosition()); pageData.put("siteId", page.getSiteId()); pageData.put("skin", page.getSkin()); pageData.put("title", page.getTitle()); pageData.put("url", page.getUrl()); if (includeProps) { // get the properties HashMap<String, String> props = new HashMap<String, String>(); ResourceProperties rp = page.getProperties(); for (Iterator<String> iterator = rp.getPropertyNames(); iterator.hasNext();) { String name = iterator.next(); String value = rp.getProperty(name); props.put(name, value); } pageData.put("properties", page.getProperties()); } List<Map<String, Object>> tools = new ArrayList<Map<String,Object>>(); pageData.put("tools", tools); // Peek into the tools to see if they want to be popped up // Similar to PortalSiteHelperImpl.java String source = null; boolean toolPopup = false; int count = 0; // get the tool configs for each for (ToolConfiguration tc : (List<ToolConfiguration>) page.getTools() ) { // get the tool from column 0 for this tool config (if there is one) Tool tool = tc.getTool(); if (tool != null) { HashMap<String, Object> toolData = new HashMap<String, Object>(); tools.add(toolData); // back to normal stuff again toolData.put("id", tc.getId()); toolData.put("toolId", tool.getId()); toolData.put("placementId", tc.getId()); toolData.put("title", tool.getTitle()); toolData.put("description", tool.getDescription()); toolData.put("url", page.getUrl()); toolData.put("home", tool.getHome()); toolData.put("context", tc.getContext()); toolData.put("pageId", tc.getPageId()); toolData.put("pageOrder", tc.getPageOrder()); toolData.put("siteId", tc.getSiteId()); if (includeConfig && admin) { toolData.put("config", tc.getConfig()); toolData.put("registeredConfig", tool.getRegisteredConfig()); toolData.put("mutableConfig", tool.getMutableConfig()); } count++; Properties toolProps = tc.getConfig(); if ( "sakai.web.168".equals(tc.getToolId()) ) { source = toolProps.getProperty("source"); toolPopup = "true".equals(toolProps.getProperty("popup")); } else if ( "sakai.iframe".equals(tc.getToolId()) ) { source = toolProps.getProperty("source"); toolPopup = "true".equals(toolProps.getProperty("popup")); } else if ( "sakai.basiclti".equals(tc.getToolId()) ) { toolPopup = "on".equals(toolProps.getProperty("imsti.newpage")); source = "/access/basiclti/site/"+tc.getContext()+"/"+tc.getId(); } } } if ( count != 1 ) { toolPopup = false; source = null; } pageData.put("toolpopup", Boolean.valueOf(toolPopup)); pageData.put("toolpopupurl", source); // Add the pageData data.add( pageData ); } return new ActionReturn(data); } /** * @param site * the site to check perms in * @return true if the current user can view this site * @throws SecurityException * if not allowed */ protected boolean isAllowedAccessMembers(Site site) { // check if the current user can access this String userReference = developerHelperService.getCurrentUserReference(); if (userReference == null) { throw new SecurityException("Anonymous users may not view memberships in (" + site.getReference() + ")"); } else { if (!siteService.allowViewRoster(site.getId())) { throw new SecurityException("Memberships in this site (" + site.getReference() + ") are not accessible for the current user: " + userReference); } } return true; } // STANDARD METHODS public boolean entityExists(String id) { if (id == null) { return false; } if ("".equals(id)) { return true; } boolean exists = siteService.siteExists(id); return exists; } public String createEntity(EntityReference ref, Object entity, Map<String, Object> params) { String siteId = null; if (ref.getId() != null && ref.getId().length() > 0) { siteId = ref.getId(); } if (entity.getClass().isAssignableFrom(Site.class)) { // if someone passes in a Site Site site = (Site) entity; if (siteId == null && site.getId() != null) { siteId = site.getId(); } // check description String description = site.getDescription(); if (description != null) { StringBuilder alertMsg = new StringBuilder(); description = FormattedText.processFormattedText(description, alertMsg); if (description == null) { throw new IllegalArgumentException("Site description markup rejected: " + alertMsg.toString()); } } Site s = null; try { s = siteService.addSite(siteId, site.getType()); s.setCustomPageOrdered(site.isCustomPageOrdered()); s.setDescription(description); s.setIconUrl(site.getIconUrl()); s.setInfoUrl(site.getInfoUrl()); s.setJoinable(site.isJoinable()); s.setJoinerRole(site.getJoinerRole()); s.setMaintainRole(site.getMaintainRole()); s.setProviderGroupId(site.getProviderGroupId()); s.setPublished(site.isPublished()); s.setPubView(site.isPubView()); s.setShortDescription(site.getShortDescription()); s.setSkin(site.getSkin()); s.setTitle(site.getTitle()); siteService.save(s); siteId = s.getId(); } catch (IdInvalidException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot create site with given id: " + siteId + ":" + e.getMessage(), e); } catch (IdUsedException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot create site with given id: " + siteId + ":" + e.getMessage(), e); } catch (PermissionException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new SecurityException( "Current user does not have permissions to create site: " + ref + ":" + e.getMessage(), e); } catch (IdUnusedException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot save new site with given id: " + siteId + ":" + e.getMessage(), e); } } else if (entity.getClass().isAssignableFrom(EntitySite.class)) { // if they instead pass in the EntitySite object EntitySite site = (EntitySite) entity; if (siteId == null && site.getId() != null) { siteId = site.getId(); } // check description String description = site.getDescription(); if (description != null) { StringBuilder alertMsg = new StringBuilder(); description = FormattedText.processFormattedText(description, alertMsg); if (description == null) { throw new IllegalArgumentException("Site description markup rejected: " + alertMsg.toString()); } } Site s = null; try { s = siteService.addSite(siteId, site.getType()); s.setCustomPageOrdered(site.isCustomPageOrdered()); s.setDescription(description); s.setIconUrl(site.getIconUrl()); s.setInfoUrl(site.getInfoUrl()); s.setJoinable(site.isJoinable()); s.setJoinerRole(site.getJoinerRole()); s.setMaintainRole(site.getMaintainRole()); s.setProviderGroupId(site.getProviderGroupId()); s.setPublished(site.isPublished()); s.setPubView(site.isPubView()); s.setShortDescription(site.getShortDescription()); s.setSkin(site.getSkin()); s.setTitle(site.getTitle()); // attempt to set the owner as requested String ownerUserId = site.getOwner(); if (ownerUserId != null) { ownerUserId = userEntityProvider.findAndCheckUserId(ownerUserId, null); if (ownerUserId == null) { throw new IllegalArgumentException( "Invalid userId supplied for owner of site: " + site.getOwner()); } ReflectUtils.getInstance().setFieldValue(s, "m_createdUserId", ownerUserId); } // save the site siteService.save(s); siteId = s.getId(); } catch (IdInvalidException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot create site with given id: " + siteId + ":" + e.getMessage(), e); } catch (IdUsedException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot create site with given id: " + siteId + ":" + e.getMessage(), e); } catch (PermissionException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new SecurityException( "Current user does not have permissions to create site: " + ref + ":" + e.getMessage(), e); } catch (IdUnusedException e) { try { siteService.removeSite(s); } catch (Exception e1) { log.warn("Could not cleanup site on create failure: " + e1); // BLANK } throw new IllegalArgumentException("Cannot save new site with given id: " + siteId + ":" + e.getMessage(), e); } } else { throw new IllegalArgumentException( "Invalid entity for creation, must be Site or EntitySite object"); } return siteId; } public Object getSampleEntity() { return new EntitySite(); } public void updateEntity(EntityReference ref, Object entity, Map<String, Object> params) { String siteId = ref.getId(); if (siteId == null) { throw new IllegalArgumentException("Cannot update, No siteId in provided reference: " + ref); } Site s = getSiteById(siteId); if (s == null) { throw new IllegalArgumentException("Cannot find site to update with id: " + siteId); } boolean admin = developerHelperService.isUserAdmin(developerHelperService.getCurrentUserReference()); if (entity.getClass().isAssignableFrom(Site.class)) { // if someone passes in a Site Site site = (Site) entity; // check description String description = site.getDescription(); if (description != null) { StringBuilder alertMsg = new StringBuilder(); description = FormattedText.processFormattedText(description, alertMsg); if (description == null) { throw new IllegalArgumentException("Site description markup rejected: " + alertMsg.toString()); } } s.setCustomPageOrdered(site.isCustomPageOrdered()); s.setDescription(description); s.setIconUrl(site.getIconUrl()); s.setInfoUrl(site.getInfoUrl()); s.setJoinable(site.isJoinable()); s.setJoinerRole(site.getJoinerRole()); s.setMaintainRole(site.getMaintainRole()); s.setProviderGroupId(site.getProviderGroupId()); s.setPublished(site.isPublished()); s.setPubView(site.isPubView()); s.setShortDescription(site.getShortDescription()); s.setSkin(site.getSkin()); s.setTitle(site.getTitle()); // put in properties if admin, otherwise ignore if (admin) { ResourcePropertiesEdit rpe = s.getPropertiesEdit(); rpe.set(site.getProperties()); } } else if (entity.getClass().isAssignableFrom(EntitySite.class)) { // if they instead pass in the entitysite object EntitySite site = (EntitySite) entity; // check description String description = site.getDescription(); if (description != null) { StringBuilder alertMsg = new StringBuilder(); description = FormattedText.processFormattedText(description, alertMsg); if (description == null) { throw new IllegalArgumentException("Site description markup rejected: " + alertMsg.toString()); } } s.setCustomPageOrdered(site.isCustomPageOrdered()); if (description != null) s.setDescription(description); if (site.getIconUrl() != null) s.setIconUrl(site.getIconUrl()); s.setJoinable(site.isJoinable()); if (site.getJoinerRole() != null) s.setJoinerRole(site.getJoinerRole()); if (site.getMaintainRole() != null) s.setMaintainRole(site.getMaintainRole()); if (site.getProviderGroupId() != null) s.setProviderGroupId(site.getProviderGroupId()); s.setPublished(site.isPublished()); s.setPubView(site.isPubView()); if (site.getShortDescription() != null) s.setShortDescription(site.getShortDescription()); if (site.getSkin() != null) s.setSkin(site.getSkin()); if (site.getTitle() != null) s.setTitle(site.getTitle()); // put in properties if admin, otherwise ignore if (admin) { ResourcePropertiesEdit rpe = s.getPropertiesEdit(); for (String key : site.getProps().keySet()) { String value = site.getProps().get(key); rpe.addProperty(key, value); } } // attempt to set the owner as requested String ownerUserId = site.getOwner(); if (ownerUserId != null) { ownerUserId = userEntityProvider.findAndCheckUserId(ownerUserId, null); if (ownerUserId == null) { throw new IllegalArgumentException( "Invalid userId supplied for owner of site: " + site.getOwner()); } ReflectUtils.getInstance().setFieldValue(s, "m_createdUserId", ownerUserId); } } else { throw new IllegalArgumentException( "Invalid entity for update, must be Site or EntitySite object"); } try { siteService.save(s); } catch (IdUnusedException e) { throw new IllegalArgumentException( "Sakai was unable to save a site which it just fetched: " + ref, e); } catch (PermissionException e) { throw new SecurityException("Current user does not have permissions to update site: " + ref + ":" + e.getMessage(), e); } } @EntityParameters(accepted = { "includeGroups" }) public Object getEntity(EntityReference ref) { boolean includeGroups = false; if (requestStorage.getStoredValue("includeGroups") != null) { includeGroups = true; } if (ref.getId() == null) { return new EntitySite(); } String siteId = ref.getId(); Site site = getSiteById(siteId); // check if the user can access site isAllowedAccessSite(site); // convert EntitySite es = new EntitySite(site, includeGroups); return es; } /** * @param site * the site to check perms in * @return true if the current user can view this site * @throws SecurityException * if not allowed */ protected boolean isAllowedAccessSite(Site site) { // check if the user can access this String userReference = developerHelperService.getCurrentUserReference(); if (userReference == null) { if (!siteService.allowAccessSite(site.getId())) { throw new SecurityException( "This site (" + site.getReference() + ") is not accessible to anon and there is no current user so the site is inaccessible"); } } else { if (!site.isPubView() && !siteService.allowAccessSite(site.getId())) { throw new SecurityException("This site (" + site.getReference() + ") is not public and is not accessible for the current user: " + userReference); } } return true; } public void deleteEntity(EntityReference ref, Map<String, Object> params) { String siteId = ref.getId(); if (siteId == null || "".equals(siteId)) { throw new IllegalArgumentException( "Cannot delete site, No siteId in provided reference: " + ref); } Site site = getSiteById(siteId); if (site != null) { try { siteService.removeSite(site); } catch (PermissionException e) { throw new SecurityException("Permission denied: Site cannot be removed: " + ref); } catch (IdUnusedException e) { throw new IllegalArgumentException( "Cannot delete site, No siteId in provided reference: " + ref); } } } @EntityParameters(accepted = { "select", "selectionType", "search", "_start", "_limit" }) public List<?> getEntities(EntityReference ref, Search search) { String criteria = null; String selectType = "access"; Restriction select = search.getRestrictionByProperty("select"); if (select == null) { select = search.getRestrictionByProperty("selectionType"); } if (select != null) { selectType = select.value + ""; } SelectionType sType = SelectionType.ACCESS; if ("access".equals(selectType)) { sType = SelectionType.ACCESS; } else if ("update".equals(selectType)) { sType = SelectionType.UPDATE; } else if ("joinable".equals(selectType)) { sType = SelectionType.JOINABLE; } else if ("pubView".equals(selectType)) { sType = SelectionType.PUBVIEW; } else { // based on the current user String userReference = developerHelperService.getCurrentUserReference(); if (userReference == null) { sType = SelectionType.PUBVIEW; } else { if (developerHelperService.isUserAdmin(userReference)) { sType = SelectionType.ANY; } } } int start = 1; if (search.getStart() > 0 && search.getStart() < Integer.MAX_VALUE) { // Search docs indicate 0-based indexing, while PagingPosition is 1-based start = (int) search.getStart() + 1; } int limit = defaultPageSize; if (search.getLimit() > 0 && search.getLimit() < Integer.MAX_VALUE) { limit = (int) search.getLimit(); } if (limit > maxPageSize) { limit = maxPageSize; } Restriction restrict = search.getRestrictionByProperty("search"); if (restrict == null) { restrict = search.getRestrictionByProperty("criteria"); } if (restrict != null) { criteria = restrict.value + ""; } List<Site> sites = siteService.getSites(sType, null, criteria, null, SortType.TITLE_ASC, new PagingPosition(start, limit)); // convert these into EntityUser objects List<EntitySite> entitySites = new ArrayList<EntitySite>(); for (Site site : sites) { EntitySite es = new EntitySite(site, false); entitySites.add(es); } return entitySites; } public String[] getHandledInputFormats() { return new String[] { Formats.HTML, Formats.XML, Formats.JSON }; } public String[] getHandledOutputFormats() { return new String[] { Formats.XML, Formats.JSON, Formats.HTML, Formats.FORM }; } private Site getSiteById(String siteId) { Site site; try { site = siteService.getSite(siteId); } catch (IdUnusedException e) { throw new IllegalArgumentException("Cannot find site by siteId: " + siteId, e); } return site; } private RequestStorage requestStorage; public void setRequestStorage(RequestStorage requestStorage) { this.requestStorage = requestStorage; } /** * Remove the users list from the group provided. User memberships must be retrieved from the * Memberships Entity Provider * * @param grp * Group to trim * @return */ protected Group trimGroupUsers(Group grp) { Group newGrp = grp; newGrp.removeMembers(); return newGrp; } /** * Only handle Site Info type groups. * * @param group * @throws IllegalArgumentException * if NOT a Site Info type group */ private void checkGroupType(Group group) { if (group != null) { try { if (!group.getProperties().getBooleanProperty(GROUP_PROP_WSETUP_CREATED)) { throw new IllegalArgumentException( "This type of group (Section Info group) should not be edited by this entity provider. Only Site info groups are allowed."); } } catch (Exception e) { throw new IllegalArgumentException( "This type of group (Section Info group) should not be edited by this entity provider. Only Site info groups are allowed."); } } } }