/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package edu.harvard.iq.dataverse.worldmapauth;
import edu.harvard.iq.dataverse.DataFile;
import edu.harvard.iq.dataverse.PermissionServiceBean;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import java.util.List;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
/**
*
* @author raprasad
*/
@Stateless
@Named
public class WorldMapTokenServiceBean {
@EJB
PermissionServiceBean permissionService;
@EJB
TokenApplicationTypeServiceBean tokenApplicationService;
private static final Logger logger = Logger.getLogger(TokenApplicationTypeServiceBean.class.getCanonicalName());
@PersistenceContext(unitName = "VDCNet-ejbPU")
private EntityManager em;
/**
*
* Retrieve a fresh token to map a Dataverse file on GeoConnect
*
* @param dataFileID
* @param dvUserID
* @return WorldMapToken
*/
public WorldMapToken getNewToken(DataFile dataFile, AuthenticatedUser dvUser){
if ((dataFile==null)||(dvUser==null)){
logger.severe("dataFile or dvUser is null");
return null;
}
WorldMapToken token = new WorldMapToken();
token.setApplication(tokenApplicationService.getGeoConnectApplication());
token.setDatafile(dataFile);
token.setDataverseUser(dvUser);
token.setModified();
token.setToken();
return this.save(token);
// return token;
// getGeoConnectApplication
}
public WorldMapToken find(Object pk) {
if (pk==null){
return null;
}
return (WorldMapToken) em.find(WorldMapToken.class, pk);
}
/**
* Expire the token, set the "hasExpired" flag to True
*
* @param wmToken
*/
public void expireToken(WorldMapToken wmToken){
if (wmToken==null){
return;
}
wmToken.expireToken();
em.merge(wmToken);
}
/**
* Expire and then Delete the token
* (The expire is a bit extraneous)
*
* @param wmToken
*/
public void deleteToken(WorldMapToken wmToken){
if (wmToken==null){
return;
}
em.remove(em.merge(wmToken));
}
/*
Remove expired tokens from the database
*/
public void deleteExpiredTokens(){
Query query = em.createQuery("select object(w) from WorldMapToken as w where w.hasExpired IS TRUE");// order by o.name");
List<WorldMapToken> tokenList = query.getResultList();
for (WorldMapToken wmToken : tokenList) {
// em.remove(token);
em.remove(em.merge(wmToken));
}
}
public WorldMapToken save( WorldMapToken dvToken ) {
if (dvToken==null){
return null;
}
if (dvToken.getToken()==null){
dvToken.setToken();
}
if (dvToken.getApplication().getMapitLink()==null){
logger.warning("mapitLink is missing for token_application");
return null;
}
TokenApplicationType dat = dvToken.getApplication();
if (dat==null){
logger.warning("TokenApplicationType is null for WorldMapToken");
return null;
}
if ( dvToken.getId()== null ) {
em.persist(dvToken);
logger.fine("New token_application saved");
return dvToken;
} else {
logger.fine("Existing token_application saved");
return em.merge( dvToken );
}
}
public WorldMapToken findByName(String token){
if (token == null){
return null;
}
try{
return em.createQuery("select m from WorldMapToken m WHERE m.token=:token", WorldMapToken.class)
.setParameter("token", token)
.getSingleResult();
} catch ( NoResultException nre ) {
return null;
}
}
/**
* Given a string token, retrieve the related WorldMapToken object
*
* @param worldmapTokenParam
* @return WorldMapToken object (if it hasn't expired)
*/
public WorldMapToken retrieveAndRefreshValidToken(String worldmapTokenParam){
if (worldmapTokenParam==null){
logger.warning("worldmapTokenParam is null. Permission denied.");
return null;
}
WorldMapToken wmToken = this.findByName(worldmapTokenParam);
if (wmToken==null){
logger.warning("WorldMapToken not found for '" + worldmapTokenParam + "'. Permission denied.");
return null;
}
if (wmToken.hasTokenExpired()){
em.remove(em.merge(wmToken)); // Delete expired token from the database.
logger.warning("WorldMapToken has expired. Permission denied.");
return null;
}
wmToken.refreshToken();
logger.info("WorldMapToken refreshed.");
this.save(wmToken);
return wmToken;
}
/*
Can the user connected to the WorldMapToken still
edit the dataset for the file connected to the token?
*/
public boolean canTokenUserEditFile(WorldMapToken wmToken){
if (wmToken==null){
return false;
}
if (permissionService.userOn(wmToken.getDataverseUser(), wmToken.getDatafile()).has(Permission.EditDataset)) {
logger.info("WorldMap token-based auth: Token's User is still authorized to edit the dataset for the datafile.");
return true;
}
return false;
}
/*
Can the user connected to the WorldMapToken still
download the file connected to the token?
*/
private boolean canTokenUserDownloadFile(WorldMapToken wmToken){
if (wmToken==null){
return false;
}
if (permissionService.userOn(wmToken.getDataverseUser(), wmToken.getDatafile()).has(Permission.DownloadFile)) {
logger.info("WorldMap token-based auth: Token's User is still authorized to download the datafile.");
return true;
}
return false;
}
/*
Given a string for a WorldMapToken and DataFile, check:
(1) Is this token valid?
(2) Does the token correspond to this DataFile?
@return boolean if token is valid and corresponds to the given DataFile
*/
public boolean isWorldMapTokenAuthorizedForDataFileDownload(String worldmapTokenParam, DataFile df){
logger.info("-- isWorldMapTokenAuthorizedForDataFileworldmapTokenParam " + worldmapTokenParam);
if ((worldmapTokenParam == null)||(df == null)){
logger.info("nope: worldmapTokenParam or data file is null");
return false;
}
// Check 1: Is this a valid WorldMap token?
//
WorldMapToken token = this.retrieveAndRefreshValidToken(worldmapTokenParam);
if (token==null){
logger.info("WorldMap token-based auth: Token is not invalid.");
return false;
}
// Check 2: Does this WorldMap token's datafile match the requested datafile?
//
if (!(token.getDatafile().getId().equals(df.getId()))){
logger.info("WorldMap token-based auth: Token's datafile does not match the requested datafile.");
return false;
}
// Check 3: Does this WorldMap token's user have permission for the requested datafile?
//
if (!(this.canTokenUserDownloadFile(token))){
logger.info("WorldMap token-based auth: Token's User is not authorized for the requested datafile.");
return false;
}
logger.info("WorldMap token-based auth: Token is valid for the requested datafile");
return true;
}
/*
Given a string for a WorldMapToken, check:
(1) Is this token valid?
(2) Re-verify that can edit the Dataset connected to the token's DataFile
@return boolean if token is valid and corresponds to the given DataFile
*/
public boolean isWorldMapTokenAuthorizedForMetadataRetrievalAndUpdates(String worldmapTokenParam){
logger.info("-- isWorldMapTokenAuthorizedForDataFile?");
if (worldmapTokenParam == null){
logger.info("nope: worldmapTokenParam or data file is null");
return false;
}
// Check 1: Is this a valid WorldMap token?
//
WorldMapToken token = this.retrieveAndRefreshValidToken(worldmapTokenParam);
if (token==null){
logger.info("WorldMap token-based auth: Token is not invalid.");
return false;
}
// Check 2: Does this WorldMap token's user still have edit permission for the requested datafile?
//
if (!(this.canTokenUserEditFile(token))){
logger.info("WorldMap token-based auth: Token's User is not authorized for the requested datafile.");
return false;
}
logger.info("WorldMap token-based auth: Token is valid for the requested datafile");
return true;
}
} // end of class