/** * PODD is an OWL ontology database used for scientific project management * * Copyright (C) 2009-2013 The University Of Queensland * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see <http://www.gnu.org/licenses/>. */ package com.github.podd.utils; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.openrdf.model.BNode; import org.openrdf.model.Literal; import org.openrdf.model.Model; import org.openrdf.model.Resource; import org.openrdf.model.URI; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.model.vocabulary.RDF; import org.restlet.security.Role; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.ansell.restletutils.RestletUtilRole; import com.github.ansell.restletutils.SesameRealmConstants; /** * The Roles available for PODD users. * * @author Peter Ansell p_ansell@yahoo.com * * Copied from http://github.com/ansell/restlet-utils */ public enum PoddRoles implements RestletUtilRole { ADMIN("Administrator", "A repository administrator of the PODD System", "http://purl.org/podd/ns/poddUser#RoleAdministrator", true), PROJECT_CREATOR("Project Creator", "A User who can create new projects", "http://purl.org/podd/ns/poddUser#RoleTopObjectCreator", true), PROJECT_MEMBER("Project Member", "A user who is a member of a particular project", "http://purl.org/podd/ns/poddUser#RoleTopObjectMember", true), PROJECT_OBSERVER("Project Observer", "A user who is an observer of a particular project", "http://purl.org/podd/ns/poddUser#RoleTopObjectObserver", true), PROJECT_ADMIN("Project Administrator", "A user who is an administrator of a particular project", "http://purl.org/podd/ns/poddUser#RoleTopObjectAdministrator", true), PROJECT_PRINCIPAL_INVESTIGATOR("Principal Investigator", "A user who is the lead of a particular project and has the ability to publish the project", "http://purl.org/podd/ns/poddUser#RoleTopObjectPrincipalInvestigator", true), ; private final static Logger log = LoggerFactory.getLogger(PoddRoles.class); private final static Set<RestletUtilRole> INTERNAL_REPOSITORY_ROLES; private final static Set<Role> INTERNAL_RESTLET_ROLES; static { final Set<RestletUtilRole> tempRepositoryRoles = new HashSet<>(); tempRepositoryRoles.add(ADMIN); tempRepositoryRoles.add(PROJECT_CREATOR); INTERNAL_REPOSITORY_ROLES = Collections.unmodifiableSet(tempRepositoryRoles); final Set<Role> tempRoles = Collections.newSetFromMap(new IdentityHashMap<Role, Boolean>()); for(final RestletUtilRole nextRole : PoddRoles.values()) { // WARNING: After Restlet-2.1RC5 Roles are only considered equal if they are the // same java object, so this must not create a new Role each time tempRoles.add(nextRole.getRole()); } INTERNAL_RESTLET_ROLES = Collections.unmodifiableSet(tempRoles); } /** * Dumps the role mappings from the given map to the given model, optionally into the given * contexts. */ public static void dumpRoleMappingsArtifact(final Map<RestletUtilRole, Collection<String>> mappings, final Model model, final URI... contexts) { for(final Entry<RestletUtilRole, Collection<String>> nextEntry : mappings.entrySet()) { final RestletUtilRole nextRole = nextEntry.getKey(); for(final String nextUserIdentifier : nextEntry.getValue()) { final BNode mappingUri = PODD.VF.createBNode(); model.add(mappingUri, RDF.TYPE, SesameRealmConstants.OAS_ROLEMAPPING, contexts); model.add(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDROLE, nextRole.getURI(), contexts); model.add(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDUSER, PODD.VF.createLiteral(nextUserIdentifier), contexts); } } } /** * Dumps the role mappings from the given map to the given model, optionally into the given * contexts. */ public static void dumpRoleMappingsUser(final Map<RestletUtilRole, Collection<URI>> mappings, final Model model, final URI... contexts) { for(final Entry<RestletUtilRole, Collection<URI>> nextEntry : mappings.entrySet()) { final RestletUtilRole nextRole = nextEntry.getKey(); for(final URI nextObjectUri : nextEntry.getValue()) { final BNode mappingUri = PODD.VF.createBNode(); model.add(mappingUri, RDF.TYPE, SesameRealmConstants.OAS_ROLEMAPPING, contexts); model.add(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDROLE, nextRole.getURI(), contexts); if(nextObjectUri != null) { model.add(mappingUri, PODD.PODD_ROLEMAPPEDOBJECT, nextObjectUri, contexts); } } } } /** * Extracts role mappings for an object, to users who have the role, from the given RDF * statements. * * @param model * A set of RDF statements defining role mappings * @return A map of roles to collections of users who have the role. */ public static Map<RestletUtilRole, Collection<String>> extractRoleMappingsArtifact(final Model model, final URI... contexts) { final ConcurrentMap<RestletUtilRole, Collection<String>> results = new ConcurrentHashMap<>(); // extract Role Mapping info (User details are ignored as multiple users are not // supported) for(final Resource mappingUri : model.filter(null, RDF.TYPE, SesameRealmConstants.OAS_ROLEMAPPING, contexts) .subjects()) { final URI roleUri = model.filter(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDROLE, null, contexts).objectURI(); final RestletUtilRole role = PoddRoles.getRoleByUri(roleUri); final Literal mappedObject = model.filter(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDUSER, null, contexts).objectLiteral(); PoddRoles.log.debug("Extracted Role <{}> with Optional Object <{}>", role.getName(), mappedObject); Collection<String> nextObjectUris = new HashSet<>(); final Collection<String> putIfAbsent = results.putIfAbsent(role, nextObjectUris); if(putIfAbsent != null) { nextObjectUris = putIfAbsent; } nextObjectUris.add(mappedObject.stringValue()); } return results; } /** * Extracts role mappings, optionally to object URIs, from the given RDF statements. * <p> * NOTE: This method does not fail if Repository roles contain object URIs or if Project Roles * do not contain object URIs. The user must determine when and how to fail in these cases. * * @param model * A set of RDF statements defining role mappings * @return A map of roles to collections of optional object URIs. If the collection contains a * null element, then the role was not mapped to an object URI in at least one case. */ public static Map<RestletUtilRole, Collection<URI>> extractRoleMappingsUser(final Model model, final URI... contexts) { final ConcurrentMap<RestletUtilRole, Collection<URI>> results = new ConcurrentHashMap<>(); // extract Role Mapping info (User details are ignored as multiple users are not // supported) for(final Resource mappingUri : model.filter(null, RDF.TYPE, SesameRealmConstants.OAS_ROLEMAPPING, contexts) .subjects()) { final URI roleUri = model.filter(mappingUri, SesameRealmConstants.OAS_ROLEMAPPEDROLE, null, contexts).objectURI(); final RestletUtilRole role = PoddRoles.getRoleByUri(roleUri); final URI mappedObject = model.filter(mappingUri, PODD.PODD_ROLEMAPPEDOBJECT, null, contexts).objectURI(); PoddRoles.log.debug("Extracted Role <{}> with Optional Object <{}>", role.getName(), mappedObject); Collection<URI> nextObjectUris = new HashSet<>(); final Collection<URI> putIfAbsent = results.putIfAbsent(role, nextObjectUris); if(putIfAbsent != null) { nextObjectUris = putIfAbsent; } nextObjectUris.add(mappedObject); } return results; } /** * @return Retrieve PoddRoles that are Repository-wide (e.g. Administrator Role) */ public static Set<RestletUtilRole> getRepositoryRoles() { return PoddRoles.INTERNAL_REPOSITORY_ROLES; } public static RestletUtilRole getRoleByName(final String name) { for(final RestletUtilRole nextRole : PoddRoles.values()) { if(nextRole.getName().equals(name)) { return nextRole; } } return null; } public static RestletUtilRole getRoleByUri(final URI nextUri) { for(final RestletUtilRole nextRole : PoddRoles.values()) { if(nextRole.getURI().equals(nextUri)) { return nextRole; } } return null; } public static Set<Role> getRoles() { return PoddRoles.INTERNAL_RESTLET_ROLES; } private final Role role; private final URI uri; private final boolean isAssignable; /** * Constructor * * @param roleName * @param description * @param uriString */ PoddRoles(final String roleName, final String description, final String uriString, final boolean isAssignable) { this.role = new Role(roleName, description); this.uri = ValueFactoryImpl.getInstance().createURI(uriString); this.isAssignable = isAssignable; } /** * @return the description */ @Override public String getDescription() { return this.role.getDescription(); } /** * @return the name */ @Override public String getName() { return this.role.getName(); } @Override public Role getRole() { return this.role; } @Override public URI getURI() { return this.uri; } @Override public boolean isAssignable() { return this.isAssignable; } }