package org.gbif.ipt.struts2;
import org.gbif.ipt.action.BaseAction;
import org.gbif.ipt.config.Constants;
import org.gbif.ipt.model.Resource;
import org.gbif.ipt.model.User;
import org.gbif.ipt.model.VersionHistory;
import org.gbif.ipt.model.voc.PublicationStatus;
import org.gbif.ipt.service.manage.ResourceManager;
import java.math.BigDecimal;
import java.util.Map;
import com.google.inject.Inject;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.commons.lang3.StringUtils;
/**
* An Interceptor that makes sure a requested resource is either public or the current user has rights to manage the
* private resource. This prevents private resources, or deleted resource from being made available.
*/
public class PrivateDeletedResourceInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2340800191217429210L;
@Inject
private ResourceManager resourceManager;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
String requestedResource = RequireManagerInterceptor.getResourceParam(invocation);
if (requestedResource != null) {
// does resource exist at all?
Resource resource = resourceManager.get(requestedResource);
if (resource == null) {
return BaseAction.NOT_FOUND;
}
// get current user
Map<String, Object> session = invocation.getInvocationContext().getSession();
User user = (User) session.get(Constants.SESSION_USER);
// is the resource version requested private, or has it been deleted?
String requestedResourceVersion = getResourceVersionParam(invocation);
if (requestedResourceVersion != null) {
try {
BigDecimal version = new BigDecimal(requestedResourceVersion);
VersionHistory history = resource.findVersionHistory(version);
if (history != null) {
if (history.getPublicationStatus() == PublicationStatus.PRIVATE) {
// user authorised?
if (user == null || !isAuthorized(user, resource)) {
return BaseAction.NOT_ALLOWED;
}
} else if (history.getPublicationStatus() == PublicationStatus.DELETED) {
// user authorised?
if (user == null || !isAuthorized(user, resource)) {
return BaseAction.NOT_AVAILABLE;
}
}
}
} catch (NumberFormatException e) {
// return 404 if version was in incorrect format
return BaseAction.NOT_FOUND;
}
}
// is the resource currently private, or has it been deleted?
if (PublicationStatus.PRIVATE == resource.getStatus()) {
// user authorised?
if (user == null || !isAuthorized(user, resource)) {
return BaseAction.NOT_ALLOWED;
}
} else if (PublicationStatus.DELETED == resource.getStatus()) {
// user authorised?
if (user == null || !isAuthorized(user, resource)) {
return BaseAction.NOT_AVAILABLE;
}
}
}
return invocation.invoke();
}
private boolean isAuthorized(User user, Resource resource) {
if (user.hasAdminRights()) {
return true;
}
if (resource != null && resource.getCreator().equals(user)) {
return true;
}
if (user.hasManagerRights()) {
for (User m : resource.getManagers()) {
if (user.equals(m)) {
return true;
}
}
}
return false;
}
/**
* @return the value for the version parameter (e.g. v=1.3, this method should return "1.3")
*/
private static String getResourceVersionParam(ActionInvocation invocation) {
String version = null;
Object requestedResourceVersion = invocation.getInvocationContext().getParameters().get(Constants.REQ_PARAM_VERSION);
if (requestedResourceVersion != null && requestedResourceVersion.getClass().isArray()
&& ((Object[]) requestedResourceVersion).length == 1) {
version = StringUtils.trimToNull(((Object[]) requestedResourceVersion)[0].toString());
}
return version;
}
}