/**********************************************************************************
* $URL:https://source.sakaiproject.org/svn/osp/trunk/common/api-impl/src/java/org/theospi/portfolio/security/mgt/impl/PermissionManagerImpl.java $
* $Id:PermissionManagerImpl.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 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.security.mgt.impl;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.GroupAlreadyDefinedException;
import org.sakaiproject.authz.api.GroupIdInvalidException;
import org.sakaiproject.authz.api.GroupNotDefinedException;
import org.sakaiproject.authz.api.Role;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzPermissionException;
import org.sakaiproject.authz.api.RoleAlreadyDefinedException;
import org.sakaiproject.authz.cover.AuthzGroupService;
import org.sakaiproject.metaobj.shared.mgt.AgentManager;
import org.sakaiproject.metaobj.shared.model.Agent;
import org.sakaiproject.metaobj.shared.model.Id;
import org.sakaiproject.metaobj.shared.model.OspRole;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.cover.EntityManager;
import org.sakaiproject.exception.IdUnusedException;
import org.theospi.portfolio.security.Authorization;
import org.theospi.portfolio.security.AuthorizationFacade;
import org.theospi.portfolio.security.mgt.PermissionManager;
import org.theospi.portfolio.security.mgt.ToolPermissionManager;
import org.theospi.portfolio.security.model.Permission;
import org.theospi.portfolio.security.model.PermissionsEdit;
import org.theospi.portfolio.shared.model.OspException;
public class PermissionManagerImpl implements PermissionManager {
protected final transient Log logger = LogFactory.getLog(getClass());
private AgentManager agentManager;
private AuthorizationFacade authzManager;
private Map tools;
public List getWorksiteRoles(PermissionsEdit edit) {
AuthzGroup authzGroup = getAuthzGroup(edit, false);
Set roles = authzGroup.getRoles();
List returned = new ArrayList();
returned.addAll(roles);
return returned;
}
public PermissionsEdit fillPermissions(PermissionsEdit edit) {
return fillPermissions(edit, false);
}
public PermissionsEdit fillPermissions(PermissionsEdit edit, boolean useQualifier) {
edit.setPermissions(new ArrayList());
edit = fillPermissionsInternal(edit, edit.getQualifier(), false, useQualifier);
ToolPermissionManager mgr = getToolManager(edit);
List quals = mgr.getReadOnlyQualifiers(edit);
for (Iterator i=quals.iterator();i.hasNext();) {
Id qualifier = (Id)i.next();
fillPermissionsInternal(edit, qualifier, true, useQualifier);
}
return edit;
}
protected PermissionsEdit fillPermissionsInternal(
PermissionsEdit edit, Id qualifier, boolean readOnly, boolean useQualifier) {
/*Realm siteRealm = RealmService.getRealm("/site/" +
edit.getSiteId());
Set roles = siteRealm.getRoles();
*/
AuthzGroup authzGroup = getAuthzGroup(edit, useQualifier);
if (authzGroup == null) {
return edit;
}
Set roles = authzGroup.getRoles();
Reference ref = EntityManager.newReference(authzGroup.getId());
Collection realms = ref.getAuthzGroups();
List functions = getAppFunctions(edit);
for (Iterator i=roles.iterator();i.hasNext();) {
Role role = (Role)i.next();
Agent currentRole = getAgentManager().getWorksiteRole(role.getId(), edit.getSiteId());
Set abilities = AuthzGroupService.getAllowedFunctions(role.getId(), realms);
for (Iterator j=functions.iterator();j.hasNext();) {
String func = (String) j.next();
if (abilities.contains(func)) {
edit.getPermissions().add(
new Permission(currentRole, func, readOnly));
}
}
}
return edit;
}
protected AuthzGroup getAuthzGroup(PermissionsEdit edit, boolean useQualifier) {
try {
String usedId = useQualifier ? edit.getQualifier().getValue() : "/site/" + edit.getSiteId();
return AuthzGroupService.getInstance().getAuthzGroup(usedId);
} catch (GroupNotDefinedException e) {
//This should be an okay exception to swallow. If we can't find the realm, just skip it.
// This came up when using the sites tool to create a site. Since there wasn't
// a realm yet, couldn't set permissions
if (useQualifier) {
//need to create one
AuthzGroup templateAzg = null;
Site site = null;
try {
String realmTemplate = "!matrix.template.";
site = SiteService.getSite(edit.getSiteId());
templateAzg = AuthzGroupService.getInstance().getAuthzGroup(realmTemplate + site.getType());
}
catch (GroupNotDefinedException gnde) {
logger.warn("group with id: " + gnde.getId() + " not defined", gnde);
} catch (IdUnusedException iue) {
logger.warn("id: " + iue.getId() + " not found", iue);
}
try {
AuthzGroup azg = null;
if (templateAzg != null) {
azg = AuthzGroupService.getInstance().addAuthzGroup(
edit.getQualifier().getValue(), templateAzg, null);
if (site != null && azg != null) {
purgeBadRoles(azg, site);
try {
AuthzGroupService.save(azg);
} catch (GroupNotDefinedException e1) {
logger.warn("azg no defined", e1);
//shouldn't need to do anything since it was just created
}
}
}
else {
azg = AuthzGroupService.getInstance().addAuthzGroup(
edit.getQualifier().getValue());
}
if (azg == null) {
logger.warn("azg is still null after trying to create it.");
}
else {
azg.removeMembers();
}
return azg;
} catch (GroupIdInvalidException giie) {
logger.warn("group id invalid", giie);
} catch (GroupAlreadyDefinedException gade) {
logger.warn("group already defined", gade);
} catch (AuthzPermissionException ape) {
logger.warn("Permission exception", ape);
}
}
// SAK-19632 - changed this to a debug to avoid logging unimportant warnings, added info log
String msg = "Cannot find realm corresponding to site: " + e.getId() + ". Skipping it for setting permissions.";
if (logger.isDebugEnabled()) {
// log the stacktrace
logger.debug(msg, e);
}
logger.info(msg);
//throw new OspException(e);
}
return null;
}
private void purgeBadRoles(AuthzGroup azg, Site site) {
Set<Role> activeRoles = site.getRoles();
Set<Role> azgRoles = azg.getRoles();
for (Role role: azgRoles) {
if (!activeRoles.contains(role))
azg.removeRole(role.getId());
}
}
public void updatePermissions(PermissionsEdit edit, boolean useQualifier) {
List origPermissions = null;
PermissionsEdit orig = (PermissionsEdit)edit.clone();
orig = fillPermissions(orig, useQualifier);
origPermissions = orig.getPermissions();
AuthzGroup currentGroup = getAuthzGroup(edit, useQualifier);
for (Iterator i=edit.getPermissions().iterator();i.hasNext();) {
Permission perm = (Permission)i.next();
if (origPermissions.contains(perm)) {
origPermissions.remove(perm);
}
else if (!perm.isReadOnly()) {
Role currentRole = getRole(currentGroup, perm);
currentRole.allowFunction(perm.getFunction());
}
}
for (Iterator i=origPermissions.iterator();i.hasNext();) {
Permission perm = (Permission)i.next();
Role currentRole = getRole(currentGroup, perm);
currentRole.disallowFunction(perm.getFunction());
}
try {
AuthzGroupService.save(currentGroup);
} catch (GroupNotDefinedException e) {
throw new OspException(e);
} catch (AuthzPermissionException e) {
throw new OspException(e);
}
}
protected Role getRole(AuthzGroup currentGroup, Permission perm) {
Role role = null;
if (perm.getAgent() instanceof OspRole) {
role = currentGroup.getRole(((OspRole)perm.getAgent()).getRoleName());
if (role == null) {
try {
role = currentGroup.addRole(((OspRole)perm.getAgent()).getRoleName());
} catch (RoleAlreadyDefinedException e) {
// This should never happen since we know the role was null already, but log just in case
logger.warn(e);
}
}
}
return role;
}
public void duplicatePermissions(Id srcQualifier, Id targetQualifier, Site newSite) {
AuthorizationFacade manager = getAuthzManager();
List origPermissions = manager.getAuthorizations(null, null, srcQualifier);
for (Iterator i=origPermissions.iterator();i.hasNext();) {
Authorization authz = (Authorization)i.next();
Agent agent = authz.getAgent();
if (newSite != null && agent instanceof OspRole) {
agent = getAgentManager().getTempWorksiteRole(
((OspRole)agent).getRoleName(), newSite.getId());
}
if (agent != null) {
manager.createAuthorization(agent, authz.getFunction(), targetQualifier);
}
}
}
public void addTools(Map newTools) {
getTools().putAll(newTools);
}
public List getAppFunctions(PermissionsEdit edit) {
ToolPermissionManager mgr = getToolManager(edit);
return mgr.getFunctions(edit);
}
protected ToolPermissionManager getToolManager(PermissionsEdit edit) {
return (ToolPermissionManager)getTools().get(edit.getName());
}
public AgentManager getAgentManager() {
return agentManager;
}
public void setAgentManager(AgentManager agentManager) {
this.agentManager = agentManager;
}
public AuthorizationFacade getAuthzManager() {
return authzManager;
}
public void setAuthzManager(AuthorizationFacade authzManager) {
this.authzManager = authzManager;
}
public Map getTools() {
return tools;
}
public void setTools(Map tools) {
this.tools = tools;
}
}