package org.kvj.lima1.gae.sync.data;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.files.AppEngineFile.FileSystem;
public class UserStorage {
private static Logger log = LoggerFactory.getLogger(UserStorage.class);
private static final String SALT = "lima1sync";
private static String passwordToHash(String password) {
MessageDigest algorithm;
try {
algorithm = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
log.error("Error in password hashing", e);
return password;
}
algorithm.reset();
algorithm.update(new String(password+SALT).getBytes());
byte[] messageDigest = algorithm.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
}
return hexString.toString();
}
public static String authorizeUser(String username, String password, String token) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Transaction txn = datastore.beginTransaction();
try {
String uName = username.toLowerCase().trim();
String pass = passwordToHash(password);
Query existing = new Query("User").addFilter("username", FilterOperator.EQUAL, uName);
Entity user = datastore.prepare(existing).asSingleEntity();
if (null == user) {
log.info("User {} isn't exists - creating", uName);
user = new Entity("User");
user.setProperty("username", uName);
user.setProperty("password", pass);
user.setProperty("created", new Date().getTime());
datastore.put(txn, user);
txn.commit();
txn = datastore.beginTransaction();
}
log.info("Checking password for entity: {}", user.getKey());
if (!pass.equals(user.getProperty("password"))) {
log.warn("Password in incorrect for user "+uName+": "+pass);
return "Password is incorrect";
}
log.info("Storing token");
Entity tokenEntity = new Entity("Token", user.getKey());
tokenEntity.setProperty("token", token);
tokenEntity.setProperty("user", user.getKey());
tokenEntity.setProperty("issued", new Date().getTime());
tokenEntity.setProperty("accessed", new Date().getTime());
datastore.put(txn, tokenEntity);
txn.commit();
log.info("Token created");
return null;
} catch (Exception e) {
log.error("Users error", e);
return "DB error";
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
public static String verifyToken(String token) {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Transaction txn = datastore.beginTransaction();
try {
Query searchToken = new Query("Token").
addFilter("token", FilterOperator.EQUAL, token);
Entity tokenEntity = datastore.prepare(searchToken).asSingleEntity();
if (null == tokenEntity) {
log.warn("Token {} not found - error", token);
return null;
}
log.info("Updating token");
tokenEntity.setProperty("accessed", new Date().getTime());
datastore.put(txn, tokenEntity);
txn.commit();
log.info("Token OK");
Entity userEntity = datastore.get((Key) tokenEntity.getProperty("user"));
return (String) userEntity.getProperty("username");
} catch (Exception e) {
log.error("Token error", e);
return null;
} finally {
if (txn.isActive()) {
txn.rollback();
}
}
}
}