/*****************************************************************************************
Infosistema - OpenBaas
Copyright(C) 2002-2014 Infosistema, S.A.
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/>.
www.infosistema.com
info@openbaas.com
Av. José Gomes Ferreira, 11 3rd floor, s.34
Miraflores
1495-139 Algés Portugal
****************************************************************************************/
package infosistema.openbaas.dataaccess.models;
import infosistema.openbaas.utils.Const;
import infosistema.openbaas.utils.Log;
import infosistema.openbaas.utils.geolocation.Geo;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Sessions are stored in a separate redis instance, this redis instance is used
* only for session operations.
*
* Redis Sessions Instance -> Sessions Redis Cache Instance -> Everything else
* (users/apps/ect)
*
*/
public class SessionModel {
// *** CONTRUCTORS *** //
private SessionModel() {
JedisPoolConfig poolConf = new JedisPoolConfig();
poolConf.setMaxActive(2);
poolConf.setMaxWait(10000);
pool = new JedisPool(poolConf, Const.getRedisSessionServer(), Const.getRedisSessionPort());
userModel = UserModel.getInstance();
geo = Geo.getInstance();
}
private static SessionModel instance = null;
public static SessionModel getInstance() {
if (instance == null) instance = new SessionModel();
return instance;
}
private JedisPool pool;
// *** PRIVATE *** //
private Geo geo;
private UserModel userModel;
// *** CONSTANTS *** //
// *** KEYS *** //
// *** CREATE *** //
public void createAdmin(String OPENBAASADMIN, byte[] adminSalt, byte[] adminHash) throws UnsupportedEncodingException {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
jedis.hset(OPENBAASADMIN, "adminSalt", new String(adminSalt,"ISO-8859-1"));
jedis.hset(OPENBAASADMIN, "adminHash", new String(adminHash,"ISO-8859-1"));
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
/**
* For sessions we use Redis expire mechanism, keys with more than 24 hours
* are automatically removed.
*
* @param sessionId
* @param userId
*/
public void createSession(String sessionId, String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());;
try {
jedis.sadd("sessions:set", sessionId);
jedis.hset("sessions:" + sessionId, Const.USER_ID, userId);
jedis.expire("sessions:" + sessionId, Const.getSessionExpireTime());
jedis.sadd("user:sessions:" + userId, sessionId);
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
// *** UPDATE *** //
/**
* Updates the session time, if it had 10 hours left until being deleted
* after we call refreshSession it will have EXPIRETIME until it is deleted
* (by default 24 hours).
*/
public boolean refreshSession(String sessionToken, String location, String date, String userAgent) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
jedis.expire("sessions:" + sessionToken, Const.getSessionExpireTime());
jedis.hset("sessions:" + sessionToken, "date", date);
boolean locationHasChange = false;
if (location != null && !"".equals(location)) {
String previousLocation = jedis.hget("sessions:" + sessionToken, Const.LOCATION);
if (previousLocation == null){
locationHasChange = true;
previousLocation = "0:0";
}
String[] previousLocationArray = previousLocation.split(":");
String[] currentLocationArray = location.split(":");
double previousLatitudeValue, previousLongitudeValue, currentLatitudeValue, currentLongitudeValue;
try{
previousLatitudeValue = Double.parseDouble(previousLocationArray[0]);
previousLongitudeValue = Double.parseDouble(previousLocationArray[1]);
currentLatitudeValue = Double.parseDouble(currentLocationArray[0]);
currentLongitudeValue = Double.parseDouble(currentLocationArray[1]);
}catch (NumberFormatException e){
Log.error("", this, "refreshSession", "Wrong number format of " +
"previousLocationArray[0]=" + previousLocationArray[0] + " or " +
"previousLocationArray[1=]=" + previousLocationArray[1] + " or " +
"currentLocationArray[0]=" + currentLocationArray[0] + " or " +
"currentLocationArray[1]=" + currentLocationArray[1], e);
return false;
}
// Test if distance < MAXIMUM DISTANCE Spherical Law of Cosines
double dist = geo.distance(previousLatitudeValue, previousLongitudeValue, currentLatitudeValue, currentLongitudeValue);
locationHasChange = (dist >= 1);
}
if (locationHasChange) {
String userId = this.getUserIdUsingSessionToken(sessionToken);
String appId = this.getAppUsingSessionToken(sessionToken);
updateLocationToSession(appId, userId, sessionToken, location);
jedis.hset("sessions:" + sessionToken, Const.LOCATION, location);
}
}catch(Exception e){
Log.error("", "refreshSession", "refreshSession", e.toString());
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return true;
}
private void updateLocationToSession(String appId, String userId, String sessionToken, String location) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
jedis.hset("sessions:" + sessionToken, Const.LOCATION, location);
userModel.updateUserLocation(appId, userId, location);
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
// *** DELETE *** //
// *** GET LIST *** //
// *** GET *** //
public Map<String, String> getAdminFields(String OPENBAASADMIN) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
Map<String, String> adminFields = null;
try {
adminFields = jedis.hgetAll(OPENBAASADMIN);
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return adminFields;
}
// *** OTHERS *** //
public boolean adminExists(String admin) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean adminExists = false;
try {
if (jedis.exists(admin))
adminExists = true;
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return adminExists;
}
public void createSession(String sessionId, String appId, String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
jedis.sadd("sessions:set", sessionId);
jedis.hset("sessions:" + sessionId, Const.APP_ID, appId);
jedis.hset("sessions:" + sessionId, Const.USER_ID, userId);
jedis.expire("sessions:" + sessionId, Const.getSessionExpireTime());
jedis.sadd("user:sessions:" + userId, sessionId);
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
public Map<String, String> getSessionFields(String sessionId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
Map<String, String> sessionFields = null;
try {
sessionFields = jedis.hgetAll("sessions:" + sessionId);
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sessionFields;
}
public boolean sessionTokenExists(String sessionId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean sucess = false;
try {
Set<String> sessionIds = jedis.smembers("sessions:set");
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()) {
if (it.next().equalsIgnoreCase(sessionId) && jedis.exists("sessions:" + sessionId)){
sucess = true;
break;
}
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sucess;
}
public boolean sessionTokenExistsForUser(String sessionToken, String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean sucess = false;
try {
Set<String> sessionIds = jedis.smembers("user:sessions:" + userId);
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()) {
String sessionId = it.next();
if (jedis.exists("sessions:" + sessionId) && sessionId.equalsIgnoreCase(sessionToken))
sucess = true;
else
jedis.srem("user:sessions:" + userId, sessionId);
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sucess;
}
public void deleteAdminSession(String adminId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
Set<String> sessionIds = jedis.smembers("sessions");
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()) {
String id = it.next();
Map<String, String> sessionFields = jedis.hgetAll("sessions:" + id);
String stmp = null;
try {
stmp = sessionFields.get(Const.USER_ID);
if (stmp.equalsIgnoreCase(adminId)) {
jedis.del("sessions:" + id);
jedis.srem("sessions", adminId);
}
} catch (Exception e) { }
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
public void createAdminSession(String sessionId, String adminId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
try {
jedis.sadd("sessions", sessionId);
jedis.hset("sessions:" + sessionId, "adminId", adminId);
jedis.expire("sessions:" + sessionId, Const.getSessionExpireTime());
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
}
public boolean deleteUserSession(String sessionToken, String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean sucess = false;
try {
Set<String> sessionIds = jedis.smembers("user:sessions:" + userId);
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()) {
String sessionId = it.next();
if (sessionId.equalsIgnoreCase(sessionToken)) {
jedis.srem("user:sessions:" + userId, sessionId);
jedis.srem("sessions", sessionId);
jedis.del("sessions:" + sessionId);
sucess = true;
}
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sucess;
}
public String getUserSession(String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
String sessionId = null;
try {
Set<String> sessionIds = jedis.smembers("sessions");
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()) {
String id = it.next();
Map<String, String> sessionFields = jedis.hgetAll("sessions:" + id);
try {
String stmp = sessionFields.get(Const.USER_ID);
if (stmp.equalsIgnoreCase(userId) && jedis.exists("sessions:" + id))
sessionId = id;
} catch (Exception e) { }
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sessionId;
}
public boolean deleteAllUserSessions(String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean sucess = false;
try {
if (jedis.exists("user:sessions:" + userId)) {
jedis.del("user:sessions:" + userId);
sucess = true;
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return sucess;
}
public Set<String> getAllUserSessions(String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
Set<String> userSessions = null;
try {
if (jedis.exists("user:sessions:" + userId)) {
userSessions = jedis.smembers("user:sessions:" + userId);
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return userSessions;
}
public boolean sessionExistsForUser(String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean exists = false;
try {
Set<String> sessionIds = jedis.smembers("user:sessions:" + userId);
Iterator<String> it = sessionIds.iterator();
if (it.hasNext())
exists = true;
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return exists;
}
public boolean isUserOnline(String userId) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
boolean exists = false;
try {
Set<String> sessionIds = jedis.smembers("user:sessions:" + userId);
Iterator<String> it = sessionIds.iterator();
while (it.hasNext()){
String sessionName = it.next();
Long userTime = jedis.ttl("sessions:"+sessionName);
if (userTime != -1)
exists = true;
}
} finally {
pool.returnResource(jedis);
}
//pool.destroy();
return exists;
}
public String getAppIdForSessionToken(String sessionToken) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
String retApp = null;
try {
retApp = jedis.hget("sessions:"+sessionToken, Const.APP_ID);
}finally {
pool.returnResource(jedis);
}
return retApp;
}
private String getAppUsingSessionToken(String sessionToken) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
String res = null;
try {
res = jedis.hget("sessions:" + sessionToken, Const.APP_ID);
}finally {
pool.returnResource(jedis);
}
return res;
}
public String getUserIdUsingSessionToken(String sessionToken) {
Jedis jedis = pool.getResource();
jedis.auth(Const.getRedisSessionPass());
String res = null;
try {
res = jedis.hget("sessions:" + sessionToken, Const.USER_ID);
}finally {
pool.returnResource(jedis);
}
return res;
}
}