/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016
*
* Licensed 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
*
* http://www.apache.org/licenses/LICENSE-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.glite.security.voms.admin.operations;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.lang.builder.StandardToStringStyle;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.glite.security.voms.admin.error.NullArgumentException;
import org.glite.security.voms.admin.error.VOMSAuthorizationException;
import org.glite.security.voms.admin.error.VOMSFatalException;
import org.glite.security.voms.admin.persistence.dao.VOMSGroupDAO;
import org.glite.security.voms.admin.persistence.error.VOMSInconsistentDatabaseException;
import org.glite.security.voms.admin.persistence.model.ACL;
import org.glite.security.voms.admin.persistence.model.VOMSGroup;
public abstract class BaseVomsOperation<V> implements VOMSOperation<V> {
static {
StandardToStringStyle stss = new StandardToStringStyle();
stss.setUseClassName(false);
stss.setUseIdentityHashCode(false);
ToStringBuilder.setDefaultStyle(stss);
}
protected Map<VOMSContext, VOMSPermission> __requiredPermissions = null;
private static final Logger __log = LoggerFactory
.getLogger(BaseVomsOperation.class);
private boolean permissionsInitialized() {
if (__requiredPermissions == null || __requiredPermissions.isEmpty())
return false;
return true;
}
protected final void addRequiredPermission(VOMSContext ctxt, VOMSPermission p) {
if (ctxt == null)
throw new NullArgumentException(
"Cannot add a null context to required permissions");
if (p == null)
throw new NullArgumentException(
"Cannot set a null permission for a context.");
__requiredPermissions.put(ctxt, p);
}
protected final void addRequiredPermissionOnAllGroups(VOMSPermission p) {
Iterator<VOMSGroup> allGroups = VOMSGroupDAO.instance().findAll()
.iterator();
while (allGroups.hasNext()) {
addRequiredPermission(VOMSContext.instance((VOMSGroup) allGroups.next()),
p);
}
}
protected final void addRequiredPermissionOnPath(VOMSGroup leafGroup,
VOMSPermission p) {
if (leafGroup == null)
throw new NullArgumentException(
"Cannot add a null context to required permissions");
if (p == null)
throw new NullArgumentException(
"Cannot set a null permission for a context.");
addRequiredPermission(VOMSContext.instance(leafGroup), p);
VOMSGroup parent = leafGroup.getParent();
do {
addRequiredPermission(VOMSContext.instance(parent), p);
parent = parent.getParent();
} while (!parent.isRootGroup());
}
protected BaseVomsOperation() {
__requiredPermissions = new HashMap<VOMSContext, VOMSPermission>();
}
protected AuthorizationResponse isAllowed() {
CurrentAdmin admin = CurrentAdmin.instance();
if (!permissionsInitialized())
setupPermissions();
if (__requiredPermissions.isEmpty())
throw new VOMSFatalException("Required permissions not defined for "
+ getName() + " operation!");
Iterator<VOMSContext> contexts = __requiredPermissions.keySet().iterator();
while (contexts.hasNext()) {
VOMSContext ctxt = contexts.next();
VOMSPermission requiredPerms = __requiredPermissions.get(ctxt);
ACL acl = ctxt.getACL();
if (acl == null)
throw new VOMSInconsistentDatabaseException(
"ACL not found for context \"" + ctxt + "\".");
if (!admin.hasPermissions(ctxt, requiredPerms))
return AuthorizationResponse.deny(ctxt, requiredPerms);
}
return AuthorizationResponse.permit();
}
public final V execute() {
logOperation();
AuthorizationResponse response = isAllowed();
if (!response.isAllowed())
throw new VOMSAuthorizationException(CurrentAdmin.instance().getAdmin(),
this, response);
return doExecute();
}
protected abstract void setupPermissions();
protected abstract V doExecute();
protected final void addRequiredPermissionsOnPath(VOMSGroup g, VOMSPermission p) {
VOMSGroup parentGroup = g.getParent();
do {
__log.debug("Adding required permission " + p + " for group: "
+ parentGroup);
addRequiredPermission(VOMSContext.instance(parentGroup), p);
parentGroup = parentGroup.getParent();
} while (!parentGroup.isRootGroup());
addRequiredPermission(VOMSContext.instance(parentGroup), p);
}
protected final void logRequiredPermissions() {
__log.debug("[" + this.getClass() + "] requiredPerms: "
+ ToStringBuilder.reflectionToString(__requiredPermissions) + "");
}
protected final String logOperationMessage() {
StringBuffer logStr = new StringBuffer();
String opName = getName();
logStr.append(opName + "(");
logStr.append(logArgs());
logStr.append(")");
return logStr.toString();
}
protected String logArgs() {
String message = ToStringBuilder.reflectionToString(this);
// FIXME: really a quick n' dirty trick to build these LOG messages...:(
message = message.replaceAll(",?__\\p{Alpha}*=[^,\\]]*,?", "");
return message;
}
protected final void logOperation() {
String adminSubj = CurrentAdmin.instance().getRealSubject();
String adminIssuer = CurrentAdmin.instance().getRealIssuer();
String message = String.format("Operation: %s - (%s,%s)",
logOperationMessage(), adminSubj, adminIssuer);
__log.info(message);
}
public String getName() {
String clazzName = this.getClass().getName();
return clazzName.substring(clazzName.lastIndexOf('.') + 1);
}
public final Map<VOMSContext, VOMSPermission> getRequiredPermissions() {
if (!permissionsInitialized())
setupPermissions();
return __requiredPermissions;
}
}