package crmdna.user; import com.googlecode.objectify.ObjectifyFilter; import com.googlecode.objectify.Work; import crmdna.client.Client; import crmdna.common.Utils; import crmdna.common.api.APIException; import crmdna.common.api.APIResponse.Status; import crmdna.sequence.Sequence; import crmdna.sequence.Sequence.SequenceType; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static crmdna.common.AssertUtils.ensure; import static crmdna.common.AssertUtils.ensureNotNull; import static crmdna.common.OfyService.ofy; public class UserCore { static final String DELIMITER = "||"; static UserProp create(String namespace, String email, long groupId) { Utils.ensureValidEmail(email); email = email.toLowerCase(); UserEntity entity = ofy(namespace).load().type(UserEntity.class).id(email).now(); if (null != entity) throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message( "There is already an user with email [" + email + "]"); UserEntity userEntity = new UserEntity(); userEntity.email = email; userEntity.userId = Sequence.getNext(namespace, SequenceType.USER); userEntity.groupId = groupId; ofy(namespace).save().entity(userEntity).now(); return userEntity.toProp(namespace); } static UserProp updateEmail(String namespace, String existingEmail, String newEmail) { Utils.ensureValidEmail(newEmail); existingEmail = existingEmail.toLowerCase(); newEmail = newEmail.toLowerCase(); UserEntity existingEntity = UserCore.safeGet(namespace, existingEmail); if (existingEmail.equals(newEmail)) return existingEntity.toProp(namespace); // newEmail should not already exist if (null != get(namespace, newEmail)) throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message( "There is already an user with email [" + newEmail + "]"); UserEntity newEntity = new UserEntity(); newEntity.email = newEmail; newEntity.userId = existingEntity.userId; newEntity.groupId = existingEntity.groupId; newEntity.privileges = existingEntity.privileges; ofy(namespace).save().entity(newEntity); ofy(namespace).delete().entity(existingEntity); ObjectifyFilter.complete(); return newEntity.toProp(namespace); } static UserProp updateGroup(final String namespace, final String email, final long newGroupId) { // email should be present safeGet(namespace, email.toLowerCase()); UserProp userProp = ofy(namespace).transact(new Work<UserProp>() { @Override public UserProp run() { UserEntity userEntity = ofy(namespace).load().type(UserEntity.class).id(email.toLowerCase()).now(); if (null == userEntity) throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message( "There is no user with email [" + email + "]"); userEntity.groupId = newGroupId; ofy(namespace).save().entity(userEntity).now(); return userEntity.toProp(namespace); } }); return userProp; } static UserEntity get(String namespace, String email) { email = email.toLowerCase(); UserEntity entity = ofy(namespace).load().type(UserEntity.class).id(email).now(); if (entity == null) return null; return entity; } public static UserEntity safeGet(String client, String email) { UserEntity userEntity = get(client, email); if (null == userEntity) throw new APIException("User [" + email + "] is not valid").status(Status.ERROR_INVALID_USER); return userEntity; } public static List<UserProp> getAll(String namespace) { Client.ensureValid(namespace); List<UserEntity> entities = ofy(namespace).load().type(UserEntity.class).order("__key__").list(); List<UserProp> props = new ArrayList<>(); for (UserEntity entity : entities) { props.add(entity.toProp(namespace)); } return props; } public static List<UserProp> getAllForGroup(String namespace, long groupId) { List<UserProp> all = getAll(namespace); List<UserProp> userProps = new ArrayList<>(); for (UserProp userProp : all) { if (userProp.groupId == groupId) userProps.add(userProp); } return userProps; } static UserProp addOrDeletePrivilege(final String namespace, final String email, final String resourceType, final String resourceId, final String privilege, final boolean add) { safeGet(namespace, email.toLowerCase()); // ensures user is valid UserProp userProp = ofy(namespace).transact(new Work<UserProp>() { @Override public UserProp run() { UserEntity userEntity = ofy(namespace).load().type(UserEntity.class).id(email.toLowerCase()).now(); if (null == userEntity) throw new APIException().status(Status.ERROR_INVALID_USER).message( "Invalid user [" + email + "]"); String rawprivilege = getRawPrivilege(resourceType, resourceId, privilege); boolean change; if (add) change = userEntity.privileges.add(rawprivilege); else change = userEntity.privileges.remove(rawprivilege); if (change) ofy(namespace).save().entity(userEntity).now(); return userEntity.toProp(namespace); } }); return userProp; } static UserProp clonePrivileges(final String namespace, final String sourceEmail, final String targetEmail) { if (null == sourceEmail) Utils.throwIncorrectSpecException("sourceUser cannot be null"); if (null == targetEmail) Utils.throwIncorrectSpecException("targetUser cannot be null"); safeGet(namespace, sourceEmail.toLowerCase()); safeGet(namespace, targetEmail.toLowerCase()); UserProp userProp = ofy(namespace).transact(new Work<UserProp>() { @Override public UserProp run() { UserEntity sourceEntity = ofy(namespace).load().type(UserEntity.class).id(sourceEmail.toLowerCase()).now(); if (null == sourceEntity) throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message( "Source email [" + sourceEmail + "] does not exist"); UserEntity targetEntity = ofy(namespace).load().type(UserEntity.class).id(targetEmail.toLowerCase()).now(); if (null == targetEntity) throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message( "Target email [" + targetEmail + "] does not exist"); targetEntity.privileges = sourceEntity.privileges; ofy(namespace).save().entity(targetEntity).now(); return targetEntity.toProp(namespace); } }); return userProp; } public static void ensureValidUser(String client, String login) { ensureNotNull(client, "client is null"); ensure(!client.isEmpty(), "client is empty"); if (null == login) throw new APIException().status(Status.ERROR_LOGIN_REQUIRED).message( "Email cannot be null or empty"); if (UserCore.isSuperUser(login)) return; login = login.toLowerCase(); UserEntity userEntity = ofy(client).load().type(UserEntity.class).id(login).now(); if (null == userEntity) throw new APIException("Invalid user [" + login + "] for client [" + client + "]") .status(Status.ERROR_INVALID_USER); } static boolean hasPrivilege(String client, String login, String resourceType, String resourceId, String privilege) { ensureNotNull(client, "client is null"); ensure(!client.isEmpty(), "client is empty"); if (null == login) throw new APIException().status(Status.ERROR_LOGIN_REQUIRED).message( "Email cannot be null or empty"); if (UserCore.isSuperUser(login)) return true; login = login.toLowerCase(); UserEntity userEntity = ofy(client).load().type(UserEntity.class).id(login).now(); if (null == userEntity) throw new APIException("Invalid user [" + login + "] for client [" + client + "]") .status(Status.ERROR_INVALID_USER); String rawPrivilege = getRawPrivilege(resourceType, resourceId, privilege); if (userEntity.privileges.contains(rawPrivilege)) return true; else return false; } static String getRawPrivilege(String resourceType, String resourceId, String action) { return resourceType.toString() + DELIMITER + resourceId + DELIMITER + action.toString(); } public static boolean isSuperUser(String login) { if (login == null) { return false; } String[] superUsers = {"sathyanarayanant@gmail.com", "thulasidhar@gmail.com"}; return Arrays.asList(superUsers).contains(login.toLowerCase()); } }