EmailsRestController.java
package sk.iway.iwcm.dmail.rest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.common.CloudToolsForCore;
import sk.iway.iwcm.components.users.userdetail.UserDetailsRepository;
import sk.iway.iwcm.components.users.userdetail.UserDetailsService;
import sk.iway.iwcm.database.SimpleQuery;
import sk.iway.iwcm.dmail.DmailUtil;
import sk.iway.iwcm.dmail.Sender;
import sk.iway.iwcm.dmail.jpa.CampaingsEntity;
import sk.iway.iwcm.dmail.jpa.CampaingsRepository;
import sk.iway.iwcm.dmail.jpa.EmailsEntity;
import sk.iway.iwcm.dmail.jpa.EmailsRepository;
import sk.iway.iwcm.dmail.jpa.StatClicksRepository;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.system.datatable.Datatable;
import sk.iway.iwcm.system.datatable.DatatablePageImpl;
import sk.iway.iwcm.system.datatable.DatatableRestControllerV2;
import sk.iway.iwcm.system.datatable.NotifyBean;
import sk.iway.iwcm.system.datatable.NotifyBean.NotifyType;
import sk.iway.iwcm.system.datatable.ProcessItemAction;
import sk.iway.iwcm.users.UserGroupsDB;
@RestController
@RequestMapping("/admin/rest/dmail/emails")
@PreAuthorize("@WebjetSecurityService.hasPermission('menuEmail')")
@Datatable
public class EmailsRestController extends DatatableRestControllerV2<EmailsEntity, Long> {
private final EmailsRepository emailsRepository;
private final CampaingsRepository campaingsRepository;
private final StatClicksRepository statClicksRepository;
private final UserDetailsRepository userDetailsRepository;
private static final String NEW_LINE = "<br><br>";
@Autowired
public EmailsRestController(EmailsRepository emailsRepository, CampaingsRepository campaingsRepository, StatClicksRepository statClicksRepository, UserDetailsRepository userDetailsRepository) {
super(emailsRepository);
this.emailsRepository = emailsRepository;
this.campaingsRepository = campaingsRepository;
this.statClicksRepository = statClicksRepository;
this.userDetailsRepository = userDetailsRepository;
}
@Override
public Page<EmailsEntity> getAllItems(Pageable pageable) {
DatatablePageImpl<EmailsEntity> page = null;
String selectType = getRequest().getParameter("selectType");
Long campainId = Long.valueOf(Tools.getIntValue(getRequest().getParameter("campainId"), -1));
if (campainId<1L) campainId = (long)-getUser().getUserId();
if(selectType != null && !selectType.isEmpty()) {
if(selectType.equals("recipients")) {
page = new DatatablePageImpl<>(emailsRepository.findAllByCampainIdAndDomainId(campainId, CloudToolsForCore.getDomainId() , pageable));
} else if(selectType.equals("opens")) {
page = new DatatablePageImpl<>(emailsRepository.findAllByCampainIdAndDomainIdAndSeenDateIsNotNull(campainId, CloudToolsForCore.getDomainId(), pageable));
} else {
//Empty page
page = new DatatablePageImpl<>(new ArrayList<>());
}
} else {
page = new DatatablePageImpl<>(emailsRepository.findAll(pageable));
}
processFromEntity(page, ProcessItemAction.GETALL);
page.addOptions("groupIds", UserGroupsDB.getInstance().getUserGroups(), "userGroupName", "userGroupId", false);
return page;
}
@Override
public EmailsEntity editItem(EmailsEntity entity, long id) {
/*Extract email - ONLY IF importing
* Example: from "Janko Tester <tester@test.sk>" do JUST "tester@test.sk"
*/
if(isImporting() == true) {
entity.setRecipientEmail( DmailUtil.parseEmailFromNameEmailFormat(entity.getRecipientEmail()) );
}
//Now remove unwanted characters
entity.setRecipientEmail( entity.getRecipientEmail().replaceAll("[<>]", "") );
//In editor can be put more than one email adress BUT if it's IMPORT action it's allways 1 email
String[] emailsToInsert;
if(isImporting() == true) {
emailsToInsert = new String[]{entity.getRecipientEmail()};
} else {
emailsToInsert = Tools.getTokens(entity.getRecipientEmail(), ",;\n\s", true);
}
//This is replacement for raw/hand insert of emails (not thru CSV/Excel)
Set<String> emailsTable = new HashSet<>();
Set<String> unsubscribedEmails = DmailUtil.getUnsubscribedEmails();
Long campainId = Long.valueOf(Tools.getIntValue(getRequest().getParameter("campainId"), -1));
CampaingsEntity campaign = (campainId > 0L) ? campaingsRepository.getById(campainId) : null;
//Load allready pushed emails in DB
for (String email : emailsRepository.getAllCampainEmails( DmailService.getCampaignId(campaign, getUser()), CloudToolsForCore.getDomainId()) ) {
emailsTable.add(email.toLowerCase());
}
//Skip wrong one so import can continue
//Prepare message for user
boolean skipWrongEmails = isImporting() == true ? isSkipWrongData() : entity.isSkipWrongEmails();
StringBuilder warningMsg = new StringBuilder("");
//Check if emailsToInsert are valid
EmailsEntity saved = null;
for(String recipientEmail : emailsToInsert) {
//Get rid of white-spaces (for safety reason)
recipientEmail = recipientEmail.replaceAll("\\s+","");
//Validate email
if(Tools.isEmail(recipientEmail) == false) {
if(skipWrongEmails == false) {
throwError( getProp().getText("email_validation.error.invalid", recipientEmail) );
} else {
//Skip
warningMsg.append( getProp().getText("email_validation.error.invalid", recipientEmail) ).append(NEW_LINE);
continue;
}
}
//Protection against unsubscribed email addresses
if(unsubscribedEmails.contains(recipientEmail.toLowerCase())) {
warningMsg.append( getProp().getText("emails.error.unsubscribed", recipientEmail) ).append(NEW_LINE);
continue;
}
//Email duplicity protection
if(emailsTable.contains(recipientEmail.toLowerCase())) {
if (emailsToInsert.length==1 && (entity.getId()!=null && entity.getId()>0)) {
//ak je v zozname len jeden email a uz ma v DB idecko, tak pokracuj, ulozime jeho zmeny
} else {
warningMsg.append( getProp().getText("emails.error.duplicit_or_exist", recipientEmail) ).append(NEW_LINE);
continue;
}
}
EmailsEntity emailToInsert;
if (emailsToInsert.length==1) emailToInsert = entity;
else emailToInsert = new EmailsEntity(recipientEmail, entity.getRecipientName());
boolean prepareSuccess = DmailService.prepareEmailForInsert(campaign, getUser().getUserId(), emailToInsert);
if(prepareSuccess == false) continue;
//Save entity into DB
if (saved == null) saved = emailsRepository.save(emailToInsert);
else emailsRepository.save(emailToInsert);
//Update emails table (because there can be duplicity in excel)
emailsTable.add(recipientEmail.toLowerCase());
}
setForceReload(true);
//Show warning message
if(warningMsg.length() > 0) {
addNotify(new NotifyBean(getProp().getText("emails.error.title"), warningMsg.toString(), NotifyType.WARNING));
}
return saved;
}
@Override
public EmailsEntity insertItem(EmailsEntity entity) {
//Insert item fn is override and dont save any entity
//Save step is allready made in beforeSave fn
return editItem(entity, -1);
}
@Override
public boolean beforeDelete(EmailsEntity entity) {
statClicksRepository.deleteByEmailId( entity.getId() );
return true;
}
@Override
public EmailsEntity processFromEntity(EmailsEntity entity, ProcessItemAction action) {
if (entity == null) return null;
Prop prop = getProp();
String keyPrefix = "components.dmail.campaings.email.status.";
if (entity.getRetry()!=null && entity.getSentDate()!=null && entity.getRetry().intValue()<0) entity.setStatus(prop.getText(keyPrefix+"error"));
else if(entity.getCreatedByUserId()!=null && entity.getCreatedByUserId() < 0) entity.setStatus(prop.getText(keyPrefix+"temporal"));
else if (Boolean.TRUE.equals(entity.getDisabled())) entity.setStatus(prop.getText(keyPrefix+"disabled"));
else if (entity.getSentDate()!=null) entity.setStatus(prop.getText(keyPrefix+"sent"));
else entity.setStatus(prop.getText(keyPrefix+"saved"));
return entity;
}
@Override
public boolean processAction(EmailsEntity entity, String action) {
if ("resend".equals(action)) {
//Resend emails
try {
new SimpleQuery().execute("UPDATE emails SET sent_date = ?, retry = ?, disabled = ? WHERE email_id = ?",null, 0, false, entity.getId());
} catch (Exception e) {
Logger.error(EmailsRestController.class, e);
return false;
}
Sender.resetSenderWait();
}
else if("addRecipients".equals(action)) {
String customData = getRequest().getParameter("customData");
try {
JSONObject jsonObject = new JSONObject(customData);
Long campaingId = Tools.getLongValue( jsonObject.getString("campaingId"), -1L);
String emailsString = Tools.getStringValue( jsonObject.getString("emails"), "");
String permissionString = Tools.getStringValue( jsonObject.getString("permissions"), "");
CampaingsEntity campain;
if(campaingId > 0) {
campain = campaingsRepository.getById(campaingId);
} else {
//Problem we dont have campain yet (create fake)
campain = new CampaingsEntity();
campain.setId( Long.valueOf(-getUser().getUserId()) );
// We CANT tell which groups were selected before, because campain is not saved yet
// For savety reason, we must remove ALL emails that have recipient_user_id
emailsRepository.deleteByCampainIdAndDomainIdWhereRecipientUserIsSet(-getUser().getUserId() , CloudToolsForCore.getDomainId());
}
//This prefixes are used in FE to distinguish between emails and permissions (FE cut them out but just to be sure)
if(Tools.isNotEmpty(emailsString)) emailsString = emailsString.replace("email_", "");
if(Tools.isNotEmpty(permissionString)) permissionString = permissionString.replace("perm_", "");
Integer[] emailIds = Tools.getTokensInteger(emailsString, ",");
Integer[] permissionIds = Tools.getTokensInteger(permissionString, ",");
String selectedGroupsString = UserDetailsService.getUserGroupIds(emailIds, permissionIds);
int[] selectedGroups = Tools.getTokensInt(selectedGroupsString, ",");
int[] originalGroups = Tools.getTokensInt(campain.getUserGroupsIds(), ",");
DmailService.handleEmails(selectedGroups, originalGroups, campain, emailsRepository, userDetailsRepository, getRequest());
if(campaingId > 0) {
//Update campain user groups (if campain is allready created)
campaingsRepository.updateUserGroups(selectedGroupsString, campaingId, CloudToolsForCore.getDomainId());
}
} catch (Exception ex) {
sk.iway.iwcm.Logger.error(ex);
}
}
return true;
}
}