blob: 06acf521e3cc3500970ba4ee42173ef804e09466 [file] [log] [blame]
package de.ids_mannheim.korap.security.ac;
import de.ids_mannheim.korap.config.ContextHolder;
import de.ids_mannheim.korap.config.BeansFactory;
import de.ids_mannheim.korap.exceptions.EmptyResultException;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.interfaces.db.PolicyHandlerIface;
import de.ids_mannheim.korap.interfaces.db.ResourceOperationIface;
import de.ids_mannheim.korap.resources.KustvaktResource;
import de.ids_mannheim.korap.resources.Permissions;
import de.ids_mannheim.korap.resources.ResourceFactory;
import de.ids_mannheim.korap.security.PermissionsBuffer;
import de.ids_mannheim.korap.security.PolicyCondition;
import de.ids_mannheim.korap.security.SecurityPolicy;
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.user.User;
import lombok.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* Created by hanl on 3/20/14.
*/
//todo: use factory pattern to init resourcefinder
public class ResourceFinder {
private static final Logger jlog = LoggerFactory
.getLogger(ResourceFinder.class);
private static PolicyHandlerIface policydao;
private static Map<Class, ResourceOperationIface> resourcedaos = new HashMap<>();
private List<KustvaktResource.Container> containers;
private User user;
private ResourceFinder (User user) {
this();
this.user = user;
}
private ResourceFinder () {
this.containers = new ArrayList<>();
overrideProviders(null);
}
public static void overrideProviders (ContextHolder beans) {
if (beans == null)
beans = BeansFactory.getKustvaktContext();
if (policydao == null | resourcedaos == null) {
ResourceFinder.policydao = beans.getPolicyDbProvider();
for (ResourceOperationIface iface : beans.getResourceProviders())
resourcedaos.put(iface.type(), iface);
}
if (policydao == null | resourcedaos.isEmpty())
throw new RuntimeException("provider not set!");
}
public static <T extends KustvaktResource> Set<T> search (String path,
boolean asParent, User user, Class<T> clazz,
Permissions.Permission ... perms) throws KustvaktException {
ResourceFinder cat = init(path, asParent, user, clazz, perms);
return cat.getResources();
}
private static <T extends KustvaktResource> ResourceFinder init (
String path, boolean asParent, User user, Class<T> clazz,
Permissions.Permission ... perms) throws KustvaktException {
ResourceFinder cat = new ResourceFinder(user);
PermissionsBuffer buffer = new PermissionsBuffer();
if (perms.length == 0)
buffer.addPermissions(Permissions.Permission.READ);
buffer.addPermissions(perms);
cat.retrievePolicies(path, buffer.getPbyte(), clazz, asParent);
return cat;
}
//todo: needs to be much faster!
public static <T extends KustvaktResource> ResourceFinder init (
@NonNull User user, Class<T> clazz) throws KustvaktException {
return init(null, true, user, clazz, Permissions.Permission.READ);
}
public static <T extends KustvaktResource> Set<T> search (String name,
boolean asParent, User user, String type) throws KustvaktException {
return (Set<T>) search(name, asParent, user,
ResourceFactory.getResourceClass(type),
Permissions.Permission.READ);
}
public static <T extends KustvaktResource> Set<T> searchPublic (
Class<T> clazz) throws KustvaktException {
return searchPublicFiltered(clazz);
}
public static <T extends KustvaktResource> Set<T> searchPublicFiltered (
Class<T> clazz, String ... ids) throws KustvaktException {
overrideProviders(null);
Set<T> sets = new HashSet<>();
List<SecurityPolicy> policies = policydao.getPolicies(
new PolicyCondition(Attributes.PUBLIC_GROUP), clazz,
Permissions.Permission.READ.toByte());
List<String> id_set = Arrays.asList(ids);
for (SecurityPolicy policy : policies) {
if (id_set.isEmpty() || id_set.contains(policy.getTarget())) {
@SuppressWarnings("unchecked")
T r = (T) resourcedaos.get(KustvaktResource.class).findbyId(
policy.getTarget(), User.UserFactory.getDemoUser());
sets.add(r);
}
}
if (sets.isEmpty()){
throw new KustvaktException(StatusCodes.NO_VALUE_FOUND,
"Cannot found public resources with ids: "+id_set.toString());
}
return sets;
}
// todo: should this be working?
public static <T extends KustvaktResource> Set<T> search (User user,
Class<T> clazz) throws KustvaktException {
Set set = new HashSet();
if (user != null && !User.UserFactory.isDemo(user.getUsername()))
set = search(null, true, user, clazz, Permissions.Permission.READ);
if (set.isEmpty())
set = searchPublic(clazz);
return set;
}
private void retrievePolicies (String path, Byte b, Class type,
boolean parent) throws KustvaktException {
//fixme: throw exception to avoid susequent exceptions due to unknown origin
if (user == null | type == null)
return;
if (parent)
this.containers = policydao.getDescending(path, user, b, type);
else
this.containers = policydao.getAscending(path, user, b, type);
}
// fixme: only return field --> extra git repo!
public <T extends KustvaktResource> Set<T> getResources () {
return evaluateResources();
}
// todo: redo with less memory usage/faster
private <T extends KustvaktResource> Set<T> evaluateResources () {
Set<T> resources = new HashSet<>();
if (this.containers != null) {
for (KustvaktResource.Container c : this.containers) {
try {
T resource = (T) resourcedaos.get(KustvaktResource.class)
.findbyId(c.getPersistentID(), this.user);
if (resource != null) {
PolicyEvaluator e = PolicyEvaluator.setFlags(user,
resource);
// resource.setManaged(e.getFlag("managed", false));
resources.add(resource);
}
}
catch (KustvaktException e) {
// don't handle connection error or no handler registered!
jlog.error("Error while retrieving containers '{}' ",
this.containers);
return Collections.emptySet();
}
}
}
return resources;
}
public Set<String> getIds () {
Set<String> resources = new HashSet<>();
for (KustvaktResource.Container c : this.containers)
resources.add(c.getPersistentID());
return resources;
}
}