package edu.harvard.iq.dataverse;
import edu.harvard.iq.dataverse.authorization.DataverseRole;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.RoleAssignee;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.authorization.RoleAssignmentSet;
import edu.harvard.iq.dataverse.search.IndexAsync;
import edu.harvard.iq.dataverse.search.IndexResponse;
import edu.harvard.iq.dataverse.search.IndexServiceBean;
import edu.harvard.iq.dataverse.search.SolrIndexServiceBean;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
/**
*
* @author michael
*/
@Stateless
@Named
public class DataverseRoleServiceBean implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(IndexServiceBean.class.getCanonicalName());
@PersistenceContext(unitName = "VDCNet-ejbPU")
private EntityManager em;
@EJB RoleAssigneeServiceBean roleAssigneeService;
@EJB IndexServiceBean indexService;
@EJB SolrIndexServiceBean solrIndexService;
@EJB IndexAsync indexAsync;
public DataverseRole save( DataverseRole aRole ) {
if ( aRole.getId() == null ) {
em.persist(aRole);
/**
* @todo Why would getId be null? Should we call
* indexDefinitionPoint here too?
* A: it's null for new roles.
*/
return aRole;
} else {
DataverseRole merged = em.merge(aRole);
/**
* @todo update permissionModificationTime here.
*/
IndexResponse indexDefinitionPountResult = indexDefinitionPoint(merged.getOwner());
logger.info("aRole getId was not null. Indexing result: " + indexDefinitionPountResult);
return merged;
}
}
public RoleAssignment save( RoleAssignment assignment ) {
if ( assignment.getId() == null ) {
em.persist(assignment);
em.flush();
} else {
assignment = em.merge( assignment );
}
/**
* @todo update permissionModificationTime here.
*/
indexAsync.indexRole(assignment);
return assignment;
}
private IndexResponse indexDefinitionPoint(DvObject definitionPoint) {
/**
* @todo Do something with the index response. Was Solr down? Is
* everything ok?
*/
IndexResponse indexResponse = solrIndexService.indexPermissionsOnSelfAndChildren(definitionPoint);
return indexResponse;
}
public DataverseRole find( Long id ) {
return em.find( DataverseRole.class, id );
}
public List<DataverseRole> findAll() {
return em.createNamedQuery("DataverseRole.listAll", DataverseRole.class).getResultList();
}
public void delete( Long id ) {
em.createNamedQuery("DataverseRole.deleteById", DataverseRole.class)
.setParameter("id", id)
.executeUpdate();
}
public List<DataverseRole> findByOwnerId( Long ownerId ) {
return em.createNamedQuery("DataverseRole.findByOwnerId", DataverseRole.class)
.setParameter("ownerId", ownerId)
.getResultList();
}
public List<DataverseRole> findBuiltinRoles() {
return em.createNamedQuery("DataverseRole.findBuiltinRoles", DataverseRole.class)
.getResultList();
}
public DataverseRole findBuiltinRoleByAlias(String alias) {
return em.createNamedQuery("DataverseRole.findBuiltinRoleByAlias", DataverseRole.class)
.setParameter("alias", alias)
.getSingleResult();
}
public void revoke( Set<DataverseRole> roles, RoleAssignee assignee, DvObject defPoint ) {
for ( DataverseRole role : roles ) {
em.createNamedQuery("RoleAssignment.deleteByAssigneeIdentifier_RoleIdDefinition_PointId")
.setParameter("assigneeIdentifier", assignee.getIdentifier())
.setParameter("roleId", role.getId())
.setParameter("definitionPointId", defPoint.getId())
.executeUpdate();
em.refresh(role);
}
em.refresh(assignee);
}
public void revoke( RoleAssignment ra ) {
if ( ! em.contains(ra) ) {
ra = em.merge(ra);
}
em.remove(ra);
/**
* @todo update permissionModificationTime here.
*/
indexAsync.indexRole(ra);
}
public RoleAssignmentSet roleAssignments( User user, Dataverse dv ) {
RoleAssignmentSet retVal = new RoleAssignmentSet(user);
while ( dv != null ) {
retVal.add( directRoleAssignments(user, dv) );
if ( dv.isPermissionRoot() ) break;
dv = dv.getOwner();
}
return retVal;
}
public List<RoleAssignment> roleAssignments( Long roleId ) {
return em.createNamedQuery("RoleAssignment.listByRoleId", RoleAssignment.class)
.setParameter("roleId", roleId)
.getResultList();
}
public RoleAssignmentSet assignmentsFor( final User u, final DvObject d ) {
return d.accept( new DvObject.Visitor<RoleAssignmentSet>() {
@Override
public RoleAssignmentSet visit(Dataverse dv) {
return roleAssignments(u, dv);
}
@Override
public RoleAssignmentSet visit(Dataset ds) {
RoleAssignmentSet asgn = ds.getOwner().accept(this);
asgn.add( directRoleAssignments(u, ds) );
return asgn;
}
@Override
public RoleAssignmentSet visit(DataFile df) {
RoleAssignmentSet asgn = df.getOwner().accept(this);
asgn.add( directRoleAssignments(u, df) );
return asgn;
}
});
}
public Set<RoleAssignment> rolesAssignments( DvObject dv ) {
Set<RoleAssignment> ras = new HashSet<>();
while ( !dv.isEffectivelyPermissionRoot() ) {
ras.addAll( em.createNamedQuery("RoleAssignment.listByDefinitionPointId", RoleAssignment.class)
.setParameter("definitionPointId", dv.getId() ).getResultList() );
dv = dv.getOwner();
}
ras.addAll( em.createNamedQuery("RoleAssignment.listByDefinitionPointId", RoleAssignment.class)
.setParameter("definitionPointId", dv.getId() ).getResultList() );
return ras;
}
/**
* Retrieves the roles assignments for {@code user}, directly on {@code dv}.
* No traversal on the containment hierarchy is done.
* @param roas the user whose roles are given
* @param dvo the object where the roles are defined.
* @return Set of roles defined for the user in the given dataverse.
* @see #roleAssignments(edu.harvard.iq.dataverse.DataverseUser, edu.harvard.iq.dataverse.Dataverse)
*/
public List<RoleAssignment> directRoleAssignments( RoleAssignee roas, DvObject dvo ) {
if ( roas==null ) throw new IllegalArgumentException("RoleAssignee cannot be null");
TypedQuery<RoleAssignment> query = em.createNamedQuery(
"RoleAssignment.listByAssigneeIdentifier_DefinitionPointId",
RoleAssignment.class);
query.setParameter("assigneeIdentifier", roas.getIdentifier());
query.setParameter("definitionPointId", dvo.getId());
return query.getResultList();
}
/**
* Retrieves the roles assignments for {@code user}, directly on {@code dv}.
* No traversal on the containment hierarchy is done.
* @param dvo the object where the roles are defined.
* @return Set of roles defined for the user in the given dataverse.
* @see #roleAssignments(edu.harvard.iq.dataverse.DataverseUser, edu.harvard.iq.dataverse.Dataverse)
*/
public List<RoleAssignment> directRoleAssignments( DvObject dvo ) {
TypedQuery<RoleAssignment> query = em.createNamedQuery(
"RoleAssignment.listByDefinitionPointId",
RoleAssignment.class);
query.setParameter("definitionPointId", dvo.getId());
return query.getResultList();
}
/**
* Get all the available roles in a given dataverse, mapped by the
* dataverse that defines them. Map entries are ordered by reversed hierarchy
* (root is always last).
* @param dvId The id of dataverse whose available roles we query
* @return map of available roles.
*/
public Set<DataverseRole> availableRoles( Long dvId ) {
Dataverse dv = em.find(Dataverse.class, dvId);
Set<DataverseRole> roles = dv.getRoles();
roles.addAll(findBuiltinRoles());
while ( !dv.isEffectivelyPermissionRoot() ) {
dv = dv.getOwner();
roles.addAll( dv.getRoles() );
}
return roles;
}
public List<DataverseRole> getDataverseRolesByPermission(Permission permissionIn, Long ownerId) {
/*
For a given permission and dataverse Id get all of the roles (built-in or owned by the dataverse)
that contain that permission
*/
List<DataverseRole> rolesToCheck = findBuiltinRoles();
List<DataverseRole> retVal = new ArrayList();
rolesToCheck.addAll(findByOwnerId(ownerId));
for (DataverseRole role : rolesToCheck) {
if (role.permissions().contains(permissionIn)) {
retVal.add(role);
}
}
return retVal;
}
}