Files
SCM-Manager/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java

131 lines
4.9 KiB
Java
Raw Normal View History

2019-01-22 13:00:02 +01:00
package sonia.scm.security;
2019-01-22 14:30:56 +01:00
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.plugin.PluginLoader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
2019-01-23 12:33:34 +01:00
import java.util.HashSet;
2019-01-22 14:30:56 +01:00
import java.util.List;
import java.util.stream.Collectors;
2019-01-23 12:33:34 +01:00
import static java.util.Collections.unmodifiableCollection;
public class RepositoryPermissionProvider {
2019-01-22 13:00:02 +01:00
private static final Logger logger = LoggerFactory.getLogger(RepositoryPermissionProvider.class);
2019-01-22 14:30:56 +01:00
private static final String REPOSITORY_PERMISSION_DESCRIPTOR = "META-INF/scm/repository-permissions.xml";
2019-01-23 12:33:34 +01:00
private final Collection<String> availableVerbs;
private final Collection<RepositoryRole> availableRoles;
2019-01-22 14:30:56 +01:00
@Inject
2019-01-23 12:33:34 +01:00
public RepositoryPermissionProvider(PluginLoader pluginLoader) {
AvailableRepositoryPermissions availablePermissions = readAvailablePermissions(pluginLoader);
this.availableVerbs = unmodifiableCollection(new HashSet<>(availablePermissions.availableVerbs));
this.availableRoles = unmodifiableCollection(new HashSet<>(availablePermissions.availableRoles.stream().map(r -> new RepositoryRole(r.name, r.verbs.verbs)).collect(Collectors.toList())));
2019-01-22 14:30:56 +01:00
}
public Collection<String> availableVerbs() {
2019-01-23 12:33:34 +01:00
return availableVerbs;
2019-01-22 14:30:56 +01:00
}
2019-01-23 12:33:34 +01:00
public Collection<RepositoryRole> availableRoles() {
return availableRoles;
2019-01-22 14:30:56 +01:00
}
private static AvailableRepositoryPermissions readAvailablePermissions(PluginLoader pluginLoader) {
Collection<String> availableVerbs = new ArrayList<>();
Collection<RoleDescriptor> availableRoles = new ArrayList<>();
try {
JAXBContext context =
JAXBContext.newInstance(RepositoryPermissionsRoot.class);
// Querying permissions from uberClassLoader returns also the permissions from plugin
Enumeration<URL> descriptorEnum =
pluginLoader.getUberClassLoader().getResources(REPOSITORY_PERMISSION_DESCRIPTOR);
while (descriptorEnum.hasMoreElements()) {
URL descriptorUrl = descriptorEnum.nextElement();
logger.debug("read repository permission descriptor from {}", descriptorUrl);
2019-01-22 14:30:56 +01:00
RepositoryPermissionsRoot repositoryPermissionsRoot = parsePermissionDescriptor(context, descriptorUrl);
availableVerbs.addAll(repositoryPermissionsRoot.verbs.verbs);
availableRoles.addAll(repositoryPermissionsRoot.roles.roles);
}
} catch (IOException ex) {
logger.error("could not read permission descriptors", ex);
} catch (JAXBException ex) {
logger.error(
"could not create jaxb context to read permission descriptors", ex);
}
return new AvailableRepositoryPermissions(availableVerbs, availableRoles);
}
@SuppressWarnings("unchecked")
private static RepositoryPermissionsRoot parsePermissionDescriptor(JAXBContext context, URL descriptorUrl) {
try {
RepositoryPermissionsRoot descriptorWrapper =
(RepositoryPermissionsRoot) context.createUnmarshaller().unmarshal(
descriptorUrl);
logger.trace("repository permissions from {}: {}", descriptorUrl, descriptorWrapper.verbs.verbs);
logger.trace("repository roles from {}: {}", descriptorUrl, descriptorWrapper.roles.roles);
2019-01-22 14:30:56 +01:00
return descriptorWrapper;
} catch (JAXBException ex) {
logger.error("could not parse permission descriptor", ex);
return new RepositoryPermissionsRoot();
}
}
private static class AvailableRepositoryPermissions {
private final Collection<String> availableVerbs;
private final Collection<RoleDescriptor> availableRoles;
private AvailableRepositoryPermissions(Collection<String> availableVerbs, Collection<RoleDescriptor> availableRoles) {
2019-01-23 12:33:34 +01:00
this.availableVerbs = unmodifiableCollection(availableVerbs);
this.availableRoles = unmodifiableCollection(availableRoles);
2019-01-22 14:30:56 +01:00
}
}
@XmlRootElement(name = "repository-permissions")
@XmlAccessorType(XmlAccessType.FIELD)
private static class RepositoryPermissionsRoot {
private VerbListDescriptor verbs = new VerbListDescriptor();
private RoleListDescriptor roles = new RoleListDescriptor();
}
@XmlRootElement(name = "verbs")
private static class VerbListDescriptor {
@XmlElement(name = "verb")
private List<String> verbs = new ArrayList<>();
}
@XmlRootElement(name = "roles")
private static class RoleListDescriptor {
@XmlElement(name = "role")
private List<RoleDescriptor> roles = new ArrayList<>();
}
@XmlRootElement(name = "role")
@XmlAccessorType(XmlAccessType.FIELD)
public static class RoleDescriptor {
@XmlElement(name = "name")
private String name;
@XmlElement(name = "verbs")
private VerbListDescriptor verbs = new VerbListDescriptor();
}
2019-01-22 13:00:02 +01:00
}