/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache 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 the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>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.apereo.portal.security.remoting; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apereo.portal.groups.IEntityGroup; import org.apereo.portal.groups.IGroupMember; import org.apereo.portal.layout.dlm.remoting.IGroupListHelper; import org.apereo.portal.layout.dlm.remoting.JsonEntityBean; import org.apereo.portal.portlets.groupselector.EntityEnum; import org.apereo.portal.portlets.permissionsadmin.Assignment; import org.apereo.portal.portlets.permissionsadmin.IPermissionAdministrationHelper; import org.apereo.portal.security.IAuthorizationPrincipal; import org.apereo.portal.security.IAuthorizationService; import org.apereo.portal.security.IPermission; import org.apereo.portal.security.IPermissionStore; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.IPersonManager; import org.apereo.portal.security.provider.PermissionImpl; import org.apereo.portal.services.AuthorizationService; import org.apereo.portal.services.GroupService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; /** */ @Controller public class PermissionAssignmentMapController extends AbstractPermissionsController { protected final Log log = LogFactory.getLog(getClass()); private IGroupListHelper groupListHelper; @Autowired(required = true) public void setGroupListHelper(IGroupListHelper groupListHelper) { this.groupListHelper = groupListHelper; } private IPermissionAdministrationHelper permissionAdministrationHelper; @Autowired(required = true) public void setPermissionAdministrationHelper( IPermissionAdministrationHelper permissionAdministrationHelper) { this.permissionAdministrationHelper = permissionAdministrationHelper; } private IPersonManager personManager; @Autowired(required = true) public void setPersonManager(IPersonManager personManager) { this.personManager = personManager; } private IPermissionStore permissionStore; @Autowired public void setPermissionStore(IPermissionStore permissionStore) { this.permissionStore = permissionStore; } private IAuthorizationService authorizationService; @Autowired public void setAuthorizationService(IAuthorizationService authorizationService) { this.authorizationService = authorizationService; } @RequestMapping(value = "/updatePermission", method = RequestMethod.GET) public ModelAndView updatePermission( @RequestParam("principal") String principal, @RequestParam("assignment") String assignment, @RequestParam("principals[]") String[] principals, @RequestParam("owner") String owner, @RequestParam("activity") String activity, @RequestParam("target") String target, HttpServletRequest request, HttpServletResponse response) throws Exception { // ensure the current user is authorized to update and view permissions final IPerson currentUser = personManager.getPerson((HttpServletRequest) request); if (!permissionAdministrationHelper.canEditPermission(currentUser, target) || !permissionAdministrationHelper.canViewPermission(currentUser, target)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return null; } JsonEntityBean bean = groupListHelper.getEntityForPrincipal(principal); if (bean != null) { IAuthorizationPrincipal p = groupListHelper.getPrincipalForEntity(bean); IPermission[] directPermissions = permissionStore.select(owner, p.getPrincipalString(), activity, target, null); this.authorizationService.removePermissions(directPermissions); assignment = assignment.toUpperCase(); if (assignment.equals(Assignment.Type.GRANT.toString()) || assignment.equals(Assignment.Type.DENY.toString())) { IPermission permission = new PermissionImpl(owner); permission.setActivity(activity); permission.setPrincipal(bean.getPrincipalString()); permission.setTarget(target); permission.setType(assignment); this.authorizationService.addPermissions(new IPermission[] {permission}); } } else { log.warn( "Unable to resolve the following principal (will " + "be omitted from the list of assignments): " + principal); } return getOwners(principals, owner, activity, target, request, response); } /** * Deletes a specific permission * * @param principal * @param assignment * @param owner * @param activity * @param target * @param request * @param response * @throws Exception */ @RequestMapping(value = "/deletePermission", method = RequestMethod.POST) public void deletePermission( @RequestParam("principal") String principal, @RequestParam("owner") String owner, @RequestParam("activity") String activity, @RequestParam("target") String target, HttpServletRequest request, HttpServletResponse response) throws Exception { // ensure the current user is authorized to update and view permissions final IPerson currentUser = personManager.getPerson((HttpServletRequest) request); if (!permissionAdministrationHelper.canEditPermission(currentUser, target) || !permissionAdministrationHelper.canViewPermission(currentUser, target)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return; } JsonEntityBean bean = groupListHelper.getEntityForPrincipal(principal); if (bean != null) { IAuthorizationPrincipal p = groupListHelper.getPrincipalForEntity(bean); IPermission[] directPermissions = permissionStore.select(owner, p.getPrincipalString(), activity, target, null); this.authorizationService.removePermissions(directPermissions); } else { log.warn( "Unable to resolve the following principal (will " + "be omitted from the list of assignments): " + principal); } response.setStatus(HttpServletResponse.SC_OK); return; } @RequestMapping(value = "/permissionAssignmentMap", method = RequestMethod.GET) public ModelAndView getOwners( @RequestParam("principals[]") String[] principals, @RequestParam("owner") String owner, @RequestParam("activity") String activity, @RequestParam("target") String target, HttpServletRequest request, HttpServletResponse response) throws Exception { // ensure the current user is authorized to view permissions final IPerson currentUser = personManager.getPerson((HttpServletRequest) request); if (!permissionAdministrationHelper.canViewPermission(currentUser, target)) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return null; } // Build the set of existing assignments List<Assignment> flatAssignmentsList = new ArrayList<Assignment>(); for (String principal : principals) { JsonEntityBean bean = groupListHelper.getEntityForPrincipal(principal); if (bean != null) { IAuthorizationPrincipal p = groupListHelper.getPrincipalForEntity(bean); // first get the permissions explicitly set for this principal Assignment.Type type = getAssignmentType(p, owner, activity, target); flatAssignmentsList.add(new Assignment(principal, bean, type)); } else { log.warn( "Unable to resolve the following principal (will " + "be omitted from the list of assignments): " + principal); } } List<Assignment> assignments = new ArrayList<Assignment>(); for (Assignment a : flatAssignmentsList) { placeInHierarchy(a, assignments, owner, activity, target); } Map<String, Object> model = Collections.<String, Object>singletonMap("assignments", assignments); return new ModelAndView("jsonView", model); } private void placeInHierarchy( Assignment a, List<Assignment> hierarchy, String owner, String activity, String target) { // Assertions. if (a == null) { String msg = "Argument 'a' [Assignment] cannot be null"; throw new IllegalArgumentException(msg); } if (hierarchy == null) { String msg = "Argument 'hierarchy' cannot be null"; throw new IllegalArgumentException(msg); } // Don't add another node if the specified Assignment // is already in the hierarchy somewhere... for (Assignment root : hierarchy) { Assignment duplicate = root.findDecendentOrSelfIfExists(a.getPrincipal()); if (duplicate != null) { return; } } // To proceed, we need to know about the containing // groups (if any) for this principal... IGroupMember member = null; EntityEnum entityEnum = a.getPrincipal().getEntityType(); if (entityEnum.isGroup()) { member = GroupService.findGroup(a.getPrincipal().getId()); } else { member = GroupService.getGroupMember(a.getPrincipal().getId(), entityEnum.getClazz()); } AuthorizationService authService = AuthorizationService.instance(); Iterator<?> it = GroupService.getCompositeGroupService().findParentGroups(member); if (it.hasNext()) { // This member must be nested within its parent(s)... while (it.hasNext()) { IEntityGroup group = (IEntityGroup) it.next(); EntityEnum beanType = EntityEnum.getEntityEnum(group.getLeafType(), true); JsonEntityBean bean = new JsonEntityBean(group, beanType); Assignment parent = null; for (Assignment root : hierarchy) { parent = root.findDecendentOrSelfIfExists(bean); if (parent != null) { // We found one... parent.addChild(a); break; } } if (parent == null) { // We weren't able to integrate this node into the existing // hierarchy; we have to dig deeper, until we either (1) // find a match, or (2) reach a root; type is INHERIT, // unless (by chance) there's something specified in an // entry on grantOrDenyMap. IAuthorizationPrincipal principal = authService.newPrincipal(group); Assignment.Type assignmentType = getAssignmentType(principal, owner, activity, target); parent = new Assignment(principal.getPrincipalString(), bean, assignmentType); parent.addChild(a); placeInHierarchy(parent, hierarchy, owner, activity, target); } } } else { // This member is a root... hierarchy.add(a); } } private Assignment.Type getAssignmentType( IAuthorizationPrincipal principal, String owner, String activity, String target) { IPermission[] directPermissions = permissionStore.select( owner, principal.getPrincipalString(), activity, target, null); Assignment.Type type; if (directPermissions.length > 0) { type = directPermissions[0].getType().equals(IPermission.PERMISSION_TYPE_GRANT) ? Assignment.Type.GRANT : Assignment.Type.DENY; } else if (principal.hasPermission(owner, activity, target)) { type = Assignment.Type.INHERIT_GRANT; } else { type = Assignment.Type.INHERIT_DENY; } return type; } }