package org.karmaexchange.util;
import static org.karmaexchange.util.AdminUtil.isAdminKey;
import static org.karmaexchange.util.OfyService.ofy;
import javax.annotation.Nullable;
import org.karmaexchange.dao.User;
import org.karmaexchange.resources.msg.ErrorResponseMsg;
import org.karmaexchange.resources.msg.ErrorResponseMsg.ErrorInfo;
import com.googlecode.objectify.Key;
public final class UserService {
// We're creating a key hierarchy since it's not clear from the documentation if keys of the
// same kind one with a numeric id and one with a string id collide. It is clear that keys that
// have different parents should never collide.
private static final Key<User> RESERVED_KEY_PARENT =
Key.create(User.class, "RESERVED_KEY");
private static final Key<User> NOT_LOGGED_IN_KEY =
ReservedKeyType.createReservedKey(ReservedKeyType.NOT_LOGGED_IN);
private static final ThreadLocal<Key<User>> currentUserKey = new ThreadLocal<Key<User>>();
public enum ReservedKeyType {
ADMIN,
NOT_LOGGED_IN;
private static final String RESERVED_KEY_TYPE_SEPERATOR = ":";
public static Key<User> createReservedKey(ReservedKeyType type) {
return createReservedKey(type, null);
}
public static Key<User> createReservedKey(ReservedKeyType type, @Nullable String subType) {
if (subType == null) {
return Key.create(RESERVED_KEY_PARENT, User.class, type.toString());
} else {
return Key.create(RESERVED_KEY_PARENT, User.class,
type + RESERVED_KEY_TYPE_SEPERATOR + subType);
}
}
public static boolean isReservedKey(Key<User> key, ReservedKeyType type) {
return (key.getParent() != null) && key.getParent().equals(RESERVED_KEY_PARENT) &&
key.getName().startsWith(type.toString());
}
}
public static Key<User> getCurrentUserKey() {
return (currentUserKey.get() == null) ? NOT_LOGGED_IN_KEY : currentUserKey.get();
}
// Objectify caches this in the session cache.
public static User getCurrentUser() {
if (!isCurrentUserLoggedIn()) {
throw ErrorResponseMsg.createException("Login required", ErrorInfo.Type.LOGIN_REQUIRED);
}
User user = ofy().load().key(getCurrentUserKey()).now();
if (user == null) {
throw ErrorResponseMsg.createException("User does not exist", ErrorInfo.Type.LOGIN_REQUIRED);
}
return user;
}
public static void setCurrentUser(Key<User> user) {
currentUserKey.set(user);
}
public static void clearCurrentUser() {
currentUserKey.set(null);
}
public static boolean isCurrentUserLoggedIn() {
return !(isNotLoggedInUser() || isCurrentUserAdmin());
}
public static boolean isCurrentUserAdmin() {
return isAdminKey(getCurrentUserKey());
}
public static boolean isNotLoggedInUser() {
return getCurrentUserKey() == NOT_LOGGED_IN_KEY;
}
// Static utility methods only.
private UserService() {
}
}