package crmdna.group;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import crmdna.client.Client;
import crmdna.common.EmailConfig;
import crmdna.common.Utils;
import crmdna.common.api.APIException;
import crmdna.common.api.APIResponse.Status;
import crmdna.list.ListProp;
import crmdna.mail2.Mandrill;
import crmdna.sequence.Sequence;
import crmdna.sequence.Sequence.SequenceType;
import crmdna.user.User;
import crmdna.user.User.ClientLevelPrivilege;
import crmdna.user.User.GroupLevelPrivilege;
import crmdna.user.UserCore;
import crmdna.user.UserProp;
import java.util.*;
import static crmdna.common.AssertUtils.*;
import static crmdna.common.OfyService.ofy;
public class Group {
public static GroupProp create(String client, String displayName, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_GROUP);
String name = Utils.removeSpaceUnderscoreBracketAndHyphen(displayName.toLowerCase());
List<Key<GroupEntity>> keys =
ofy(client).load().type(GroupEntity.class).filter("name", name).keys().list();
if (keys.size() != 0)
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"There is already a group with name [" + displayName + "]");
String key = getUniqueKey(client, name);
long val = MemcacheServiceFactory.getMemcacheService().increment(key, 1, (long) 0);
if (val != 1)
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"There is already a group with name [" + displayName + "]");
GroupEntity entity = new GroupEntity();
entity.groupId = Sequence.getNext(client, SequenceType.GROUP);
entity.name = name;
entity.displayName = displayName;
ofy(client).save().entity(entity).now();
return entity.toProp();
}
private static String getUniqueKey(String namespace, String name) {
return namespace + "_" + SequenceType.GROUP + "_" + name;
}
public static GroupEntity safeGet(String client, long groupId) {
Client.ensureValid(client);
GroupEntity entity = ofy(client).load().type(GroupEntity.class).id(groupId).now();
if (null == entity)
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Group [" + groupId + "] does not exist");
return entity;
}
public static GroupEntity safeGetByIdOrName(String client, String idOrName) {
Client.ensureValid(client);
ensureNotNull(idOrName);
if (Utils.canParseAsLong(idOrName)) {
long groupId = Utils.safeParseAsLong(idOrName);
return safeGet(client, groupId);
}
// idOrName should be name
idOrName = Utils.removeSpaceUnderscoreBracketAndHyphen(idOrName.toLowerCase());
List<GroupEntity> entities =
ofy(client).load().type(GroupEntity.class).filter("name", idOrName).list();
if (entities.size() == 0)
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Group [" + idOrName + "] does not exist");
if (entities.size() > 1)
// should never come here
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT)
.message(
"Found [" + entities.size() + "] matches for group [" + idOrName
+ "]. Please specify Id");
return entities.get(0);
}
public static Map<Long, GroupProp> get(String client, Set<Long> groupIds) {
Client.ensureValid(client);
ensureNotNull(groupIds);
ensureNoNullElement(groupIds);
groupIds.remove((long) 0);
Map<Long, GroupEntity> map = ofy(client).load().type(GroupEntity.class).ids(groupIds);
Map<Long, GroupProp> props = new HashMap<>();
for (Long groupId : map.keySet()) {
props.put(groupId, map.get(groupId).toProp());
}
return props;
}
static Map<Long, GroupEntity> getEntities(String client, Set<Long> groupIds) {
Client.ensureValid(client);
return ofy(client).load().type(GroupEntity.class).ids(groupIds);
}
public static GroupProp rename(String client, long groupId, String newDisplayName, String login) {
Client.ensureValid(client);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.UPDATE_GROUP);
GroupEntity groupEntity = safeGet(client, groupId);
String newName = Utils.removeSpaceUnderscoreBracketAndHyphen(newDisplayName.toLowerCase());
if (groupEntity.name.equals(newName)) {
// ideally should be inside a transaction
groupEntity.displayName = newDisplayName;
ofy(client).save().entity(groupEntity).now();
return groupEntity.toProp();
}
List<Key<GroupEntity>> keys =
ofy(client).load().type(GroupEntity.class).filter("name", newName).keys().list();
if (keys.size() != 0)
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"There is already a center with name [" + newDisplayName + "]");
String key = getUniqueKey(client, newDisplayName);
long val = MemcacheServiceFactory.getMemcacheService().increment(key, 1, (long) 0);
if (val != 1)
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(
"There is already a center with name [" + newDisplayName + "]");
// ideally should be inside a transaction
groupEntity.name = newName;
groupEntity.displayName = newDisplayName;
ofy(client).save().entity(groupEntity).now();
return groupEntity.toProp();
}
public static List<GroupProp> getAll(String client, boolean populateLists) {
Client.ensureValid(client);
List<GroupEntity> entities = ofy(client).load().type(GroupEntity.class).order("name").list();
List<GroupProp> props = new ArrayList<>();
for (GroupEntity entity : entities) {
GroupProp groupProp = entity.toProp();
if (populateLists) {
groupProp.listProps = crmdna.list.List.querySortedProps(client, groupProp.groupId);
}
props.add(groupProp);
}
return props;
}
public static Set<Long> getAllGroupIds(String client) {
List<GroupProp> props = getAll(client, false);
Set<Long> groupIds = new HashSet<>();
for (GroupProp prop : props)
groupIds.add(prop.groupId);
return groupIds;
}
public static void ensureValidGroupIds(String client, List<Long> groupIds) {
Set<Long> allGroupIds = Group.getAllGroupIds(client);
for (int i = 0; i < groupIds.size(); i++) {
long groupId = groupIds.get(i);
if (!allGroupIds.contains(groupId))
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(
"Error in record no [" + (i + 1) + "]: Group id [" + groupIds.get(i)
+ "] does not exist");
}
}
public static void delete(String client, long groupId, String login) {
throw new APIException().status(Status.ERROR_NOT_IMPLEMENTED).message(
"This functionality is not implemented yet");
// GroupEntity groupEntity = safeGet(client, groupId);
// ofy(client).delete().entity(groupEntity).now();
}
public static PaypalApiCredentialsProp setPaypalApiCredentials(final String client,
final long groupId, final String apiLogin, final String apiPwd, final String apiSecret,
final Boolean sandbox, final Boolean disable, String login) {
Client.ensureValid(client);
User.ensureGroupLevelPrivilege(client, groupId, login,
GroupLevelPrivilege.UPDATE_PAYMENT_CONFIG);
PaypalApiCredentialsProp prop = ofy(client).transact(new Work<PaypalApiCredentialsProp>() {
@Override
public PaypalApiCredentialsProp run() {
GroupEntity groupEntity = Group.safeGet(client, groupId);
boolean changed = false;
if (apiLogin != null) {
groupEntity.paypalApiLogin = apiLogin;
changed = true;
}
if (apiPwd != null) {
groupEntity.paypalApiPwd = apiPwd;
changed = true;
}
if (apiSecret != null) {
groupEntity.paypalApiSecret = apiSecret;
changed = true;
}
if (sandbox != null) {
groupEntity.paypalApiSandbox = sandbox;
changed = true;
}
if (disable != null) {
groupEntity.paypalApiDisable = disable;
changed = true;
}
Utils.ensureNotNullOrEmpty(groupEntity.paypalApiLogin, "Paypal login is null or empty");
Utils.ensureNotNullOrEmpty(groupEntity.paypalApiPwd, "Paypal login is null or empty");
Utils.ensureNotNullOrEmpty(groupEntity.paypalApiSecret, "Paypal secret is null or empty");
if (changed)
ofy(client).save().entity(groupEntity).now();
PaypalApiCredentialsProp prop = new PaypalApiCredentialsProp();
prop.login = groupEntity.paypalApiLogin;
prop.pwd = groupEntity.paypalApiPwd;
prop.secret = groupEntity.paypalApiSecret;
prop.sandbox = groupEntity.paypalApiSandbox;
prop.disable = groupEntity.paypalApiDisable;
return prop;
}
});
return prop;
}
public static EmailConfig setMandrillApiKey(final String client, final long groupId,
final String apiKey, String login) {
Client.ensureValid(client);
User.ensureGroupLevelPrivilege(client, groupId, login, GroupLevelPrivilege.UPDATE_EMAIL_CONFIG);
Mandrill.ensureValidApiKey(apiKey);
EmailConfig emailConfigProp = ofy(client).transact(new Work<EmailConfig>() {
@Override
public EmailConfig run() {
GroupEntity groupEntity = Group.safeGet(client, groupId);
groupEntity.mandrillApiKey = apiKey;
ofy(client).save().entity(groupEntity).now();
EmailConfig emailConfigProp = new EmailConfig();
emailConfigProp.mandrillApiKey = groupEntity.mandrillApiKey;
emailConfigProp.allowedFromEmailVsName = groupEntity.allowedFromEmailVsName;
return emailConfigProp;
}
});
return emailConfigProp;
}
public static void setContactInfo(final String client, final long groupId,
final String contactEmail, final String contactName, String login) {
Client.ensureValid(client);
User.ensureGroupLevelPrivilege(client, groupId, login, GroupLevelPrivilege.UPDATE_EMAIL_CONFIG);
Utils.ensureValidEmail(contactEmail);
ofy(client).transact(new Work<GroupProp>() {
@Override
public GroupProp run() {
GroupEntity groupEntity = Group.safeGet(client, groupId);
groupEntity.contactEmail = contactEmail;
groupEntity.contactName = contactName;
groupEntity.allowedFromEmailVsName.put(contactEmail, contactName);
ofy(client).save().entity(groupEntity).now();
return groupEntity.toProp();
}
});
}
public static EmailConfig addOrDeleteAllowedEmailSender(final String client, final long groupId,
final String fromEmail, final String fromName, final boolean add, String login) {
Client.ensureValid(client);
User.ensureGroupLevelPrivilege(client, groupId, login, GroupLevelPrivilege.UPDATE_EMAIL_CONFIG);
Utils.ensureValidEmail(fromEmail);
EmailConfig emailConfigProp = ofy(client).transact(new Work<EmailConfig>() {
@Override
public EmailConfig run() {
GroupEntity groupEntity = Group.safeGet(client, groupId);
if (add) {
ensureNotNull(fromName, "fromName is null");
ensure(!fromName.isEmpty(), "fromName is null");
groupEntity.allowedFromEmailVsName.put(fromEmail.toLowerCase(), fromName);
} else
groupEntity.allowedFromEmailVsName.remove(fromEmail.toLowerCase());
ofy(client).save().entity(groupEntity).now();
EmailConfig emailConfigProp = new EmailConfig();
emailConfigProp.mandrillApiKey = groupEntity.mandrillApiKey;
emailConfigProp.allowedFromEmailVsName = groupEntity.allowedFromEmailVsName;
return emailConfigProp;
}
});
if (UserCore.isSuperUser(login))
return emailConfigProp;
UserProp userProp = User.safeGet(client, login).toProp(client);
// mask the key if user does not have access
if (!userProp.clientLevelPrivileges.contains(ClientLevelPrivilege.VIEW_API_KEY.toString()))
emailConfigProp.mandrillApiKey = EmailConfig.TEXT_API_KEY_MASKED;
return emailConfigProp;
}
public static EmailConfig getEmailConfig(String client, long groupId, String login) {
Client.ensureValid(client);
GroupEntity groupEntity = Group.safeGet(client, groupId);
User.ensureValidUser(client, login);
EmailConfig emailConfig = new EmailConfig();
EmailConfig clientEmailConfig = Client.getEmailConfig(client, login);
emailConfig.mandrillApiKey = (groupEntity.mandrillApiKey != null) ?
groupEntity.mandrillApiKey : clientEmailConfig.mandrillApiKey;
emailConfig.allowedFromEmailVsName = (groupEntity.allowedFromEmailVsName != null) ?
groupEntity.allowedFromEmailVsName : clientEmailConfig.allowedFromEmailVsName;
emailConfig.contactName = (groupEntity.contactName != null) ?
groupEntity.contactName : clientEmailConfig.contactName;
emailConfig.contactEmail = (groupEntity.contactEmail != null) ?
groupEntity.contactEmail : clientEmailConfig.contactEmail;
if (UserCore.isSuperUser(login))
return emailConfig;
UserProp userProp = User.safeGet(client, login).toProp(client);
// mask the key if user does not have access
if (!userProp.clientLevelPrivileges.contains(ClientLevelPrivilege.VIEW_API_KEY.toString()))
emailConfig.mandrillApiKey = EmailConfig.TEXT_API_KEY_MASKED;
return emailConfig;
}
public static void setEmailHtmlTemplate(final String client, final long groupId,
final EmailType emailType, final String emailTemplate, String login) {
Client.ensureValid(client);
User.ensureGroupLevelPrivilege(client, groupId, login, GroupLevelPrivilege.UPDATE_EMAIL_CONFIG);
Utils.ensureNotNullOrEmpty(emailTemplate, "Email template cannot be null or empty");
ofy(client).transact(new VoidWork() {
@Override
public void vrun() {
GroupEntity groupEntity = Group.safeGet(client, groupId);
if (emailType == EmailType.REGISTRATION_CONFIRMATION) {
groupEntity.registrationConfirmationEmailTemplate = emailTemplate;
} else if (emailType == EmailType.REGISTRATION_REMINDER) {
groupEntity.registrationReminderEmailTemplate = emailTemplate;
} else {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Invalid emailType [" + emailType + "]");
}
ofy(client).save().entity(groupEntity).now();
}
});
}
static String getEmailTemplate(String client, long groupId, EmailType emailType) {
Client.ensureValid(client);
GroupEntity groupEntity = Group.safeGet(client, groupId);
if (emailType == EmailType.REGISTRATION_CONFIRMATION) {
return groupEntity.registrationConfirmationEmailTemplate;
} else if (emailType == EmailType.REGISTRATION_REMINDER) {
return groupEntity.registrationReminderEmailTemplate;
} else {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Invalid emailType [" + emailType + "]");
}
}
public static PaypalApiCredentialsProp getPaypalApiCredentials(String client, long groupId,
String login) {
Client.ensureValid(client);
GroupEntity groupEntity = Group.safeGet(client, groupId);
User.ensureClientLevelPrivilege(client, login, ClientLevelPrivilege.VIEW_API_KEY);
PaypalApiCredentialsProp prop = new PaypalApiCredentialsProp();
prop.login = groupEntity.paypalApiLogin;
prop.pwd = groupEntity.paypalApiPwd;
prop.secret = groupEntity.paypalApiSecret;
prop.sandbox = groupEntity.paypalApiSandbox;
prop.disable = groupEntity.paypalApiDisable;
return prop;
}
public static String safeGetSenderNameFromEmail(String client, long groupId, String senderEmail) {
Client.ensureValid(client);
Group.safeGet(client, groupId);
ensureNotNull(senderEmail, "sender email is null");
EmailConfig emailConfig = Group.getEmailConfig(client, groupId, User.SUPER_USER);
String senderName = emailConfig.allowedFromEmailVsName.get(senderEmail.toLowerCase());
if (senderName == null) {
String message =
"[" + senderEmail + "] is not an allowed email sender for client [" + client + "], group ["
+ groupId + "]";
throw new APIException(message).status(Status.ERROR_RESOURCE_INCORRECT);
}
return senderName;
}
public enum EmailType {
REGISTRATION_CONFIRMATION, REGISTRATION_REMINDER
}
public static class GroupProp {
public long groupId;
public String name;
public String displayName;
public List<ListProp> listProps;
}
}