/*
* 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.authorization.users.AuthenticatedUser;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Random;
import java.util.logging.Logger;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
*
* @author raprasad
*/
@Entity
@Table(name="worldmapauth_token"
, indexes = {@Index(name = "token_value", columnList="token", unique = true)
, @Index(columnList="application_id")
, @Index(columnList="datafile_id")
, @Index(columnList="dataverseuser_id")
})
public class WorldMapToken implements java.io.Serializable {
@Transient
public static final String GEOCONNECT_TOKEN_KEY = "GEOCONNECT_TOKEN";
@Transient
public static final long MAX_HOURS_TOKEN_CAN_BE_USED = 10;
private static final Logger logger = Logger.getLogger(WorldMapToken.class.getCanonicalName());
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable=true)
private String token; // save it to get an id, then set token
@ManyToOne
@JoinColumn(nullable=false)
private TokenApplicationType application;
@ManyToOne
@JoinColumn(nullable=false)
private AuthenticatedUser dataverseUser;
@ManyToOne
@JoinColumn(nullable=false)
private DataFile dataFile;
@Column(nullable=false)
private boolean hasExpired;
@Column(nullable=false)
private Timestamp lastRefreshTime;
@Column(nullable=false)
private Timestamp modified;
@Column(nullable=false)
private Timestamp created;
public WorldMapToken(){
this.setLastRefreshTime(this.getCurrentTimestamp());
this.setCreated();
this.setModified();
}
/**
* Get property token.
* @return String, value of property token.
*/
public String getToken() {
return this.token;
}
public Long getId(){
return this.id;
}
/**
* Set property token.
* @param token new value of property token.
*/
public boolean setToken(){
if (this.token != null){
return false;
}
if ((this.dataFile==null)||(this.dataverseUser==null)){
return false;
}
MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException ex) {
logger.severe("Failed to set token for 'Map It' request!!!");
return false;
}
md.update(this.getCurrentTimestamp().toString().getBytes());
md.update(this.dataFile.toString().getBytes());
md.update(this.dataverseUser.toString().getBytes());
Random rand = new Random();
Integer rnd_int = rand.nextInt();
md.update(rnd_int.byteValue());
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
this.token = sb.toString();
//this.token = md.toString();
return true;
}
/**
* Get property application.
* @return TokenApplicationType, value of property application.
*/
public TokenApplicationType getApplication() {
return this.application;
}
/**
* Set property application.
* @param application new value of property application.
*/
public void setApplication(TokenApplicationType application) {
this.application = application;
}
/**
* Get property dataverseUser.
* @return DataverseUser, value of property dataverseUser.
*/
public AuthenticatedUser getDataverseUser() {
return this.dataverseUser;
}
/**
* Set property dataverseUser.
* @param dataverseUser new value of property dataverseUser.
*/
public void setDataverseUser(AuthenticatedUser dataverseUser) {
this.dataverseUser = dataverseUser;
}
/**
* Get property datafile.
* @return DataFile, value of property datafile.
*/
public DataFile getDatafile() {
return this.dataFile;
}
/**
* Set property datafile.
* @param datafile new value of property datafile.
*/
public void setDatafile(DataFile dataFile) {
this.dataFile = dataFile;
}
/**
* Get property hasExpired.
* @return boolean, value of property hasExpired.
*/
public boolean getHasExpired() {
return this.hasExpired;
}
/**
* Set property hasExpired.
* @param hasExpired new value of property hasExpired.
*/
public void setHasExpired(boolean hasExpired) {
this.hasExpired = hasExpired;
}
/**
* Get property lastRefreshTime.
* @return Timestamp, value of property lastRefreshTime.
*/
public Timestamp getLastRefreshTime() {
return this.lastRefreshTime;
}
/**
* Set property lastRefreshTime.
* @param lastRefreshTime new value of property lastRefreshTime.
*/
public void setLastRefreshTime(Timestamp lastRefreshTime) {
this.lastRefreshTime = this.getCurrentTimestamp();
}
/**
* Get property modified.
* @return Timestamp, value of property modified.
*/
public Timestamp getModified() {
return this.modified;
}
/**
* Set property modified.
*/
public void setModified() {
this.modified = this.getCurrentTimestamp();
}
/**
* Get property created.
* @return Timestamp, value of property created.
*/
public Timestamp getCreated() {
return this.created;
}
/**
* Set property created.
*/
public void setCreated() {
this.created = this.getCurrentTimestamp();
}
public boolean hasTokenExpired(){
logger.info("hasTokenExpired");
// long currentTime = this.getCurrentTimestamp();//new Date().getTime();
return this.hasTokenExpired(this.getCurrentTimestamp());
}
private long getElapsedHours(Timestamp currentTime, Timestamp oldTime){
// If values are null, send back an elapsed time
if ((currentTime==null)||(oldTime==null)){
return this.application.getTimeLimitSeconds() + 100000;
}
long milliseconds1 = oldTime.getTime();
long milliseconds2 = currentTime.getTime();
long diff = milliseconds2 - milliseconds1;
//long diffSeconds = diff / 1000;
//long diffMinutes = diff / (60 * 1000);
long diffHours = diff / (60 * 60 * 1000);
//long diffDays = diff / (24 * 60 * 60 * 1000);
return diffHours;
}
private long getElapsedSeconds(Timestamp currentTime, Timestamp oldTime){
// If values are null, send back an elapsed time
if ((currentTime==null)||(oldTime==null)){
return this.application.getTimeLimitSeconds() + 100000;
}
long milliseconds1 = oldTime.getTime();
long milliseconds2 = currentTime.getTime();
long diff = milliseconds2 - milliseconds1;
long diffSeconds = diff / 1000;
//long diffMinutes = diff / (60 * 1000);
//long diffHours = diff / (60 * 60 * 1000);
//long diffDays = diff / (24 * 60 * 60 * 1000);
return diffSeconds;
}
public boolean hasTokenExpired(Timestamp currentTimestamp){
logger.info("hasTokenExpired (w/timestamp)");
if (this.getHasExpired()){
return true;
}
if ((currentTimestamp==null)||(this.lastRefreshTime==null)){
this.expireToken();
return true;
}
logger.info("currentTimestamp: " + currentTimestamp);
logger.info("lastRefreshTime: " + lastRefreshTime);
//System.out.println(" ..pre diff: "+ currentTimestamp);
long hours = this.getElapsedHours(currentTimestamp, this.created);
logger.info("elapsed hours: " + hours);
if (hours > MAX_HOURS_TOKEN_CAN_BE_USED){
this.expireToken();
return true;
}
long diffSeconds = this.getElapsedSeconds(currentTimestamp, this.lastRefreshTime);
//System.out.println(" ..diffSeconds: "+ diffSeconds);
//logger.info("this.application.getTimeLimitSeconds: "+ this.application.getTimeLimitSeconds());
if (diffSeconds > this.application.getTimeLimitSeconds()){
this.expireToken();
return true;
}
return false;
}
public void expireToken(){
this.setHasExpired(true);
}
public Timestamp getCurrentTimestamp(){
return new Timestamp(new Date().getTime());
}
public boolean refreshToken(){
if (this.getHasExpired()){
return false;
}
Timestamp currentTime = this.getCurrentTimestamp();
if (this.hasTokenExpired(currentTime)){
return false;
}
this.setLastRefreshTime(currentTime);
return true;
}
}