/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.core.manager.impl;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.orcid.core.adapter.Jpa2JaxbAdapter;
import org.orcid.core.adapter.JpaJaxbNotificationAdapter;
import org.orcid.core.constants.EmailConstants;
import org.orcid.core.exception.OrcidNotFoundException;
import org.orcid.core.exception.OrcidNotificationAlreadyReadException;
import org.orcid.core.exception.WrongSourceException;
import org.orcid.core.locale.LocaleManager;
import org.orcid.core.manager.ClientDetailsEntityCacheManager;
import org.orcid.core.manager.CustomEmailManager;
import org.orcid.core.manager.EmailManager;
import org.orcid.core.manager.EncryptionManager;
import org.orcid.core.manager.LoadOptions;
import org.orcid.core.manager.NotificationManager;
import org.orcid.core.manager.OrcidProfileCacheManager;
import org.orcid.core.manager.OrcidProfileManager;
import org.orcid.core.manager.ProfileEntityCacheManager;
import org.orcid.core.manager.ProfileEntityManager;
import org.orcid.core.manager.SourceManager;
import org.orcid.core.manager.TemplateManager;
import org.orcid.core.oauth.OrcidOauth2TokenDetailService;
import org.orcid.jaxb.model.clientgroup.RedirectUriType;
import org.orcid.jaxb.model.common_v2.OrcidType;
import org.orcid.jaxb.model.message.Delegation;
import org.orcid.jaxb.model.message.DelegationDetails;
import org.orcid.jaxb.model.message.Email;
import org.orcid.jaxb.model.message.OrcidProfile;
import org.orcid.jaxb.model.message.PersonalDetails;
import org.orcid.jaxb.model.message.SendChangeNotifications;
import org.orcid.jaxb.model.message.Source;
import org.orcid.jaxb.model.notification.amended_v2.AmendedSection;
import org.orcid.jaxb.model.notification.amended_v2.NotificationAmended;
import org.orcid.jaxb.model.notification.custom_v2.NotificationCustom;
import org.orcid.jaxb.model.notification.permission_v2.AuthorizationUrl;
import org.orcid.jaxb.model.notification.permission_v2.Item;
import org.orcid.jaxb.model.notification.permission_v2.Items;
import org.orcid.jaxb.model.notification.permission_v2.NotificationPermission;
import org.orcid.jaxb.model.notification.permission_v2.NotificationPermissions;
import org.orcid.jaxb.model.notification_v2.Notification;
import org.orcid.jaxb.model.notification_v2.NotificationType;
import org.orcid.jaxb.model.record_v2.Emails;
import org.orcid.model.notification.institutional_sign_in_v2.NotificationInstitutionalConnection;
import org.orcid.persistence.dao.GenericDao;
import org.orcid.persistence.dao.NotificationDao;
import org.orcid.persistence.dao.ProfileDao;
import org.orcid.persistence.jpa.entities.ActionableNotificationEntity;
import org.orcid.persistence.jpa.entities.ClientDetailsEntity;
import org.orcid.persistence.jpa.entities.ClientRedirectUriEntity;
import org.orcid.persistence.jpa.entities.CustomEmailEntity;
import org.orcid.persistence.jpa.entities.EmailType;
import org.orcid.persistence.jpa.entities.NotificationEntity;
import org.orcid.persistence.jpa.entities.NotificationInstitutionalConnectionEntity;
import org.orcid.persistence.jpa.entities.ProfileEntity;
import org.orcid.persistence.jpa.entities.ProfileEventEntity;
import org.orcid.persistence.jpa.entities.ProfileEventType;
import org.orcid.persistence.jpa.entities.RecordNameEntity;
import org.orcid.persistence.jpa.entities.SourceEntity;
import org.orcid.pojo.ajaxForm.PojoUtil;
import org.orcid.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.MessageSource;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Will Simpson
*/
public class NotificationManagerImpl implements NotificationManager {
private static final String UPDATE_NOTIFY_ORCID_ORG = "ORCID <update@notify.orcid.org>";
private static final String SUPPORT_VERIFY_ORCID_ORG = "ORCID <support@verify.orcid.org>";
private static final String RESET_NOTIFY_ORCID_ORG = "ORCID <reset@notify.orcid.org>";
private static final String CLAIM_NOTIFY_ORCID_ORG = "ORCID <claim@notify.orcid.org>";
private static final String DEACTIVATE_NOTIFY_ORCID_ORG = "ORCID <deactivate@notify.orcid.org>";
private static final String LOCKED_NOTIFY_ORCID_ORG = "ORCID <locked@notify.orcid.org>";
private static final String AMEND_NOTIFY_ORCID_ORG = "ORCID <amend@notify.orcid.org>";
private static final String DELEGATE_NOTIFY_ORCID_ORG = "ORCID <delegate@notify.orcid.org>";
private static final String EMAIL_CHANGED_NOTIFY_ORCID_ORG = "ORCID <email-changed@notify.orcid.org>";
private static final String WILDCARD_MEMBER_NAME = "${name}";
private static final String WILDCARD_USER_NAME = "${user_name}";
private static final String WILDCARD_WEBSITE = "${website}";
private static final String WILDCARD_DESCRIPTION = "${description}";
private static final String AUTHORIZATION_END_POINT = "{0}/oauth/authorize?response_type=code&client_id={1}&scope={2}&redirect_uri={3}";
@Resource
private MessageSource messages;
@Resource
private MailGunManager mailGunManager;
private String LAST_RESORT_ORCID_USER_EMAIL_NAME = "ORCID Registry User";
private String ORCID_PRIVACY_POLICY_UPDATES = "ORCID - Privacy Policy Updates";
@Resource
private OrcidUrlManager orcidUrlManager;
private boolean apiRecordCreationEmailEnabled;
private TemplateManager templateManager;
private EncryptionManager encryptionManager;
@Resource
private GenericDao<ProfileEventEntity, Long> profileEventDao;
@Resource
private ProfileDao profileDao;
@Resource
private CustomEmailManager customEmailManager;
@Resource
private JpaJaxbNotificationAdapter notificationAdapter;
@Resource
private ProfileEntityManager profileEntityManager;
@Resource
private Jpa2JaxbAdapter jpa2JaxbAdapter;
@Resource
private NotificationDao notificationDao;
@Resource
private NotificationDao notificationDaoReadOnly;
@Resource
private SourceManager sourceManager;
@Resource
private LocaleManager localeManager;
@Resource
private OrcidOauth2TokenDetailService orcidOauth2TokenDetailService;
@Resource
private ClientDetailsEntityCacheManager clientDetailsEntityCacheManager;
@Resource
private OrcidProfileManager orcidProfileManager;
@Resource
private OrcidProfileCacheManager orcidProfileCacheManager;
@Resource
private ProfileEntityCacheManager profileEntityCacheManager;
@Resource
private EmailManager emailManager;
private static final Logger LOGGER = LoggerFactory.getLogger(NotificationManagerImpl.class);
public boolean isApiRecordCreationEmailEnabled() {
return apiRecordCreationEmailEnabled;
}
public void setApiRecordCreationEmailEnabled(boolean apiRecordCreationEmailEnabled) {
this.apiRecordCreationEmailEnabled = apiRecordCreationEmailEnabled;
}
@Required
public void setTemplateManager(TemplateManager templateManager) {
this.templateManager = templateManager;
}
@Required
public void setEncryptionManager(EncryptionManager encryptionManager) {
this.encryptionManager = encryptionManager;
}
public void setProfileEventDao(GenericDao<ProfileEventEntity, Long> profileEventDao) {
this.profileEventDao = profileEventDao;
}
public void setProfileDao(ProfileDao profileDao) {
this.profileDao = profileDao;
}
public void setSourceManager(SourceManager sourceManager) {
this.sourceManager = sourceManager;
}
public void setNotificationDao(NotificationDao notificationDao) {
this.notificationDao = notificationDao;
}
public void setMailGunManager(MailGunManager mailGunManager) {
this.mailGunManager = mailGunManager;
}
@Override
public void sendWelcomeEmail(String userOrcid, String email) {
ProfileEntity profileEntity = profileEntityCacheManager.retrieve(userOrcid);
Locale userLocale = getUserLocaleFromProfileEntity(profileEntity);
Map<String, Object> templateParams = new HashMap<String, Object>();
String subject = getSubject("email.subject.register.thanks", userLocale);
String emailName = deriveEmailFriendlyName(profileEntity);
String verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
String orcidId = userOrcid;
String baseUri = orcidUrlManager.getBaseUrl();
String baseUriHttp = orcidUrlManager.getBaseUriHttp();
templateParams.put("subject", subject);
templateParams.put("emailName", emailName);
templateParams.put("verificationUrl", verificationUrl);
templateParams.put("orcidId", orcidId);
templateParams.put("baseUri", baseUri);
templateParams.put("baseUriHttp", baseUriHttp);
SourceEntity source = sourceManager.retrieveSourceEntity();
if (source != null) {
String sourceId = source.getSourceId();
String sourceName = source.getSourceName();
// If the source is not the user itself
if (sourceId != null && !sourceId.equals(orcidId)) {
if (!PojoUtil.isEmpty(sourceName)) {
String paramValue = " " + localeManager.resolveMessage("common.through") + " " + sourceName + ".";
templateParams.put("source_name_if_exists", paramValue);
} else {
templateParams.put("source_name_if_exists", ".");
}
} else {
templateParams.put("source_name_if_exists", ".");
}
} else {
templateParams.put("source_name_if_exists", ".");
}
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("welcome_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("welcome_email_html.ftl", templateParams);
mailGunManager.sendEmail(SUPPORT_VERIFY_ORCID_ORG, email, subject, body, html);
}
@Override
public void sendOrcidDeactivateEmail(String userOrcid) {
ProfileEntity profile = profileEntityCacheManager.retrieve(userOrcid);
Locale userLocale = getUserLocaleFromProfileEntity(profile);
org.orcid.jaxb.model.record_v2.Email primaryEmail = emailManager.findPrimaryEmail(userOrcid);
Map<String, Object> templateParams = new HashMap<String, Object>();
String subject = getSubject("email.subject.deactivate", userLocale);
String email = primaryEmail.getEmail();
String encryptedEmail = encryptionManager.encryptForExternalUse(email);
String base64EncodedEmail = Base64.encodeBase64URLSafeString(encryptedEmail.getBytes());
String deactivateUrlEndpointPath = "/account/confirm-deactivate-orcid";
String emailFriendlyName = deriveEmailFriendlyName(profile);
templateParams.put("emailName", emailFriendlyName);
templateParams.put("orcid", userOrcid);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("deactivateUrlEndpoint", deactivateUrlEndpointPath + "/" + base64EncodedEmail);
templateParams.put("deactivateUrlEndpointUrl", deactivateUrlEndpointPath);
templateParams.put("subject", subject);
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("deactivate_orcid_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("deactivate_orcid_email_html.ftl", templateParams);
mailGunManager.sendEmail(DEACTIVATE_NOTIFY_ORCID_ORG, email, subject, body, html);
}
@Override
public void sendOrcidLockedEmail(String orcidToLock) {
ProfileEntity profile = profileEntityCacheManager.retrieve(orcidToLock);
Locale userLocale = getUserLocaleFromProfileEntity(profile);
String subject = getSubject("email.subject.locked", userLocale);
String email = emailManager.findPrimaryEmail(orcidToLock).getEmail();
String emailFriendlyName = deriveEmailFriendlyName(profile);
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", emailFriendlyName);
templateParams.put("orcid", orcidToLock);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("subject", subject);
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("locked_orcid_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("locked_orcid_email_html.ftl", templateParams);
mailGunManager.sendEmail(LOCKED_NOTIFY_ORCID_ORG, email, subject, body, html);
}
// look like the following is our best best for i18n emails
// http://stackoverflow.com/questions/9605828/email-internationalization-using-velocity-freemarker-templates
@Override
public void sendVerificationEmail(String userOrcid, String email) {
ProfileEntity profile = profileEntityCacheManager.retrieve(userOrcid);
Locale userLocale = getUserLocaleFromProfileEntity(profile);
String subject = getSubject("email.subject.verify_reminder", userLocale);
org.orcid.jaxb.model.record_v2.Email primaryEmail = emailManager.findPrimaryEmail(userOrcid);
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("primaryEmail", primaryEmail.getEmail());
String emailFriendlyName = deriveEmailFriendlyName(profile);
templateParams.put("emailName", emailFriendlyName);
templateParams.put("subject", subject);
String verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
templateParams.put("verificationUrl", verificationUrl);
templateParams.put("orcid", userOrcid);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("verification_email.ftl", templateParams);
String htmlBody = templateManager.processTemplate("verification_email_html.ftl", templateParams);
mailGunManager.sendEmail(SUPPORT_VERIFY_ORCID_ORG, email, subject, body, htmlBody);
}
public boolean sendServiceAnnouncement_1_For_2015(OrcidProfile orcidProfile) {
String email = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
String emailFriendlyName = deriveEmailFriendlyName(orcidProfile);
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", emailFriendlyName);
String verificationUrl = null;
verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
boolean needsVerification = !orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().isVerified()
&& orcidProfile.getType().equals(org.orcid.jaxb.model.message.OrcidType.USER) && !orcidProfile.isDeactivated();
if (needsVerification) {
templateParams.put("verificationUrl", verificationUrl);
}
String emailFrequencyUrl = createUpdateEmailFrequencyUrl(orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue());
templateParams.put("emailFrequencyUrl", emailFrequencyUrl);
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
addMessageParams(templateParams, orcidProfile);
String subject = getSubject("email.service_announcement.subject.imporant_information", orcidProfile);
String text = templateManager.processTemplate("service_announcement_1_2015.ftl", templateParams);
String html = templateManager.processTemplate("service_announcement_1_2015_html.ftl", templateParams);
boolean sent = mailGunManager.sendEmail("support@notify.orcid.org", email, subject, text, html);
return sent;
}
public String createUpdateEmailFrequencyUrl(String email) {
return createEmailBaseUrl(email, orcidUrlManager.getBaseUrl(), "notifications/frequencies");
}
// look like the following is our best best for i18n emails
// http://stackoverflow.com/questions/9605828/email-internationalization-using-velocity-freemarker-templates
public boolean sendPrivPolicyEmail2014_03(OrcidProfile orcidProfile) {
String email = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
Map<String, Object> templateParams = new HashMap<String, Object>();
String emailFriendlyName = deriveEmailFriendlyName(orcidProfile);
templateParams.put("emailName", emailFriendlyName);
if (!orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().isVerified()) {
String verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
templateParams.put("verificationUrl", verificationUrl);
}
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
addMessageParams(templateParams, orcidProfile);
String text = templateManager.processTemplate("priv_policy_upate_2014_03.ftl", templateParams);
String html = templateManager.processTemplate("priv_policy_upate_2014_03_html.ftl", templateParams);
return mailGunManager.sendEmail(UPDATE_NOTIFY_ORCID_ORG, email, ORCID_PRIVACY_POLICY_UPDATES, text, html);
}
public void addMessageParams(Map<String, Object> templateParams, OrcidProfile orcidProfile) {
Locale locale = localeManager.getLocaleFromOrcidProfile(orcidProfile);
templateParams.put("messages", this.messages);
templateParams.put("messageArgs", new Object[0]);
templateParams.put("locale", locale);
}
public void addMessageParams(Map<String, Object> templateParams, Locale locale) {
templateParams.put("messages", this.messages);
templateParams.put("messageArgs", new Object[0]);
templateParams.put("locale", locale);
}
public String getSubject(String code, OrcidProfile orcidProfile) {
Locale locale = localeManager.getLocaleFromOrcidProfile(orcidProfile);
return messages.getMessage(code, null, locale);
}
private String getSubject(String code, Locale locale) {
return messages.getMessage(code, null, locale);
}
public void sendVerificationReminderEmail(OrcidProfile orcidProfile, String email) {
Map<String, Object> templateParams = new HashMap<String, Object>();
String primaryEmail = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
templateParams.put("primaryEmail", primaryEmail);
String emailFriendlyName = deriveEmailFriendlyName(orcidProfile);
templateParams.put("emailName", emailFriendlyName);
String verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
templateParams.put("verificationUrl", verificationUrl);
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("email", email);
templateParams.put("subject", getSubject("email.subject.verify_reminder", orcidProfile));
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
addMessageParams(templateParams, orcidProfile);
// Generate body from template
String body = templateManager.processTemplate("verification_reminder_email.ftl", templateParams);
String htmlBody = templateManager.processTemplate("verification_reminder_email_html.ftl", templateParams);
mailGunManager.sendEmail(SUPPORT_VERIFY_ORCID_ORG, email, getSubject("email.subject.verify_reminder", orcidProfile), body, htmlBody);
}
@Override
public String deriveEmailFriendlyName(ProfileEntity profileEntity) {
String result = null;
if (profileEntity != null && profileEntity.getRecordNameEntity() != null) {
RecordNameEntity recordName = profileEntity.getRecordNameEntity();
if (!PojoUtil.isEmpty(recordName.getCreditName())) {
result = recordName.getCreditName();
} else {
if (!PojoUtil.isEmpty(recordName.getGivenNames()))
result = recordName.getGivenNames();
if (!PojoUtil.isEmpty(recordName.getFamilyName()))
result += " " + recordName.getFamilyName();
}
}
if (PojoUtil.isEmpty(result)) {
result = LAST_RESORT_ORCID_USER_EMAIL_NAME;
}
return result;
}
@Override
public String deriveEmailFriendlyName(OrcidProfile orcidProfile) {
if (orcidProfile.getOrcidBio() != null && orcidProfile.getOrcidBio().getPersonalDetails() != null) {
PersonalDetails personalDetails = orcidProfile.getOrcidBio().getPersonalDetails();
// all this should never be null as given names are required for
// all...
if (personalDetails.getCreditName() != null)
if (!PojoUtil.isEmpty(personalDetails.getCreditName().getContent()))
return personalDetails.getCreditName().getContent();
if (personalDetails.getGivenNames() != null) {
String givenName = personalDetails.getGivenNames().getContent();
String familyName = personalDetails.getFamilyName() != null && !StringUtils.isBlank(personalDetails.getFamilyName().getContent())
? " " + personalDetails.getFamilyName().getContent() : "";
return givenName + familyName;
}
}
return LAST_RESORT_ORCID_USER_EMAIL_NAME;
}
@Override
public void sendPasswordResetEmail(String submittedEmail, OrcidProfile orcidProfile) {
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", deriveEmailFriendlyName(orcidProfile));
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("subject", getSubject("email.subject.reset", orcidProfile));
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
// Generate body from template
String resetUrl = createResetEmail(orcidProfile, orcidUrlManager.getBaseUrl());
templateParams.put("passwordResetUrl", resetUrl);
addMessageParams(templateParams, orcidProfile);
// Generate body from template
String body = templateManager.processTemplate("reset_password_email.ftl", templateParams);
String htmlBody = templateManager.processTemplate("reset_password_email_html.ftl", templateParams);
mailGunManager.sendEmail(RESET_NOTIFY_ORCID_ORG, submittedEmail, getSubject("email.subject.reset", orcidProfile), body, htmlBody);
}
@Override
public void sendReactivationEmail(String submittedEmail, OrcidProfile orcidProfile) {
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", deriveEmailFriendlyName(orcidProfile));
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("subject", getSubject("email.subject.reactivation", orcidProfile));
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
// Generate body from template
String reactivationUrl = createReactivationUrl(submittedEmail, orcidUrlManager.getBaseUrl());
templateParams.put("reactivationUrl", reactivationUrl);
addMessageParams(templateParams, orcidProfile);
// Generate body from template
String body = templateManager.processTemplate("reactivation_email.ftl", templateParams);
String htmlBody = templateManager.processTemplate("reactivation_email_html.ftl", templateParams);
mailGunManager.sendEmail(RESET_NOTIFY_ORCID_ORG, submittedEmail, getSubject("email.subject.reactivation", orcidProfile), body, htmlBody);
}
@Override
public void sendAmendEmail(OrcidProfile amendedProfile, AmendedSection amendedSection) {
sendAmendEmail(amendedProfile, amendedSection, null);
}
@Override
public void sendAmendEmail(String orcid, AmendedSection amendedSection, Item item) {
OrcidProfile amendedProfile = orcidProfileManager.retrieveOrcidProfile(orcid, LoadOptions.BIO_AND_INTERNAL_ONLY);
Collection<Item> items = new ArrayList<Item>(1);
if(item != null) {
items.add(item);
}
sendAmendEmail(amendedProfile, amendedSection, items);
}
@Override
public void sendAmendEmail(OrcidProfile amendedProfile, AmendedSection amendedSection, Collection<Item> items) {
String amenderOrcid = sourceManager.retrieveSourceOrcid();
if (amenderOrcid == null) {
LOGGER.debug("Not sending amend email, because amender is null: {}", amendedProfile);
return;
}
if (amenderOrcid.equals(amendedProfile.getOrcidIdentifier().getPath())) {
LOGGER.debug("Not sending amend email, because self edited: {}", amendedProfile);
return;
}
SendChangeNotifications sendChangeNotifications = amendedProfile.getOrcidInternal().getPreferences().getSendChangeNotifications();
if (sendChangeNotifications == null || !sendChangeNotifications.isValue()) {
LOGGER.debug("Not sending amend email, because option to send change notifications not set to true: {}", amendedProfile);
return;
}
if (OrcidType.ADMIN.equals(profileDao.retrieveOrcidType(amenderOrcid))) {
LOGGER.debug("Not sending amend email, because modified by admin ({}): {}", amenderOrcid, amendedProfile);
return;
}
String subject = getSubject("email.subject.amend", amendedProfile);
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", deriveEmailFriendlyName(amendedProfile));
templateParams.put("orcid", amendedProfile.getOrcidIdentifier().getPath());
templateParams.put("amenderName", extractAmenderName(amendedProfile, amenderOrcid));
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("subject", subject);
addMessageParams(templateParams, amendedProfile);
// Generate body from template
String body = templateManager.processTemplate("amend_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("amend_email_html.ftl", templateParams);
boolean notificationsEnabled = profileEntityCacheManager.retrieve(amendedProfile.getOrcidIdentifier().getPath()).getEnableNotifications();
if (notificationsEnabled) {
NotificationAmended notification = new NotificationAmended();
notification.setNotificationType(NotificationType.AMENDED);
notification.setAmendedSection(amendedSection);
if (items != null) {
notification.setItems(new Items(new ArrayList<>(items)));
}
createNotification(amendedProfile.getOrcidIdentifier().getPath(), notification);
} else {
String email = amendedProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
mailGunManager.sendEmail(AMEND_NOTIFY_ORCID_ORG, email, subject, body, html);
}
}
@Override
@Transactional
public void sendNotificationToAddedDelegate(String userGrantingPermission, DelegationDetails ... delegatesGrantedByUser) {
ProfileEntity profile = profileEntityCacheManager.retrieve(userGrantingPermission);
Locale userLocale = getUserLocaleFromProfileEntity(profile);
String subject = getSubject("email.subject.added_as_delegate", userLocale);
for (DelegationDetails newDelegation : delegatesGrantedByUser) {
ProfileEntity delegateProfileEntity = profileDao.find(newDelegation.getDelegateSummary().getOrcidIdentifier().getPath());
Boolean sendAdministrativeChangeNotifications = delegateProfileEntity.getSendAdministrativeChangeNotifications();
if (sendAdministrativeChangeNotifications == null || !sendAdministrativeChangeNotifications) {
LOGGER.debug("Not sending added delegate email, because option to send administrative change notifications not set to true for delegate: {}",
delegateProfileEntity.getId());
return;
}
org.orcid.jaxb.model.record_v2.Email primaryEmail = emailManager.findPrimaryEmail(userGrantingPermission);
String grantingOrcidEmail = primaryEmail.getEmail();
String emailNameForDelegate = deriveEmailFriendlyName(delegateProfileEntity);
String email = delegateProfileEntity.getPrimaryEmail().getId();
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailNameForDelegate", emailNameForDelegate);
templateParams.put("grantingOrcidValue", userGrantingPermission);
templateParams.put("grantingOrcidName", deriveEmailFriendlyName(profile));
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("grantingOrcidEmail", grantingOrcidEmail);
templateParams.put("subject", subject);
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("added_as_delegate_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("added_as_delegate_email_html.ftl", templateParams);
boolean notificationsEnabled = delegateProfileEntity.getEnableNotifications();
if (notificationsEnabled) {
NotificationCustom notification = new NotificationCustom();
notification.setNotificationType(NotificationType.CUSTOM);
notification.setSubject(subject);
notification.setBodyHtml(html);
createNotification(newDelegation.getDelegateSummary().getOrcidIdentifier().getPath(), notification);
} else {
mailGunManager.sendEmail(DELEGATE_NOTIFY_ORCID_ORG, email, subject, body, html);
}
}
}
@Override
public void sendEmailAddressChangedNotification(String currentUserOrcid, String newEmail, String oldEmail) {
ProfileEntity profile = profileEntityCacheManager.retrieve(currentUserOrcid);
Locale userLocale = getUserLocaleFromProfileEntity(profile);
// build up old template
Map<String, Object> templateParams = new HashMap<String, Object>();
String subject = getSubject("email.subject.email_removed", userLocale);
String emailFriendlyName = deriveEmailFriendlyName(profile);
templateParams.put("emailName", emailFriendlyName);
String verificationUrl = createVerificationUrl(newEmail, orcidUrlManager.getBaseUrl());
templateParams.put("verificationUrl", verificationUrl);
templateParams.put("oldEmail", oldEmail);
templateParams.put("newEmail", newEmail);
templateParams.put("orcid", currentUserOrcid);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("subject", subject);
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("email_removed.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("email_removed_html.ftl", templateParams);
mailGunManager.sendEmail(EMAIL_CHANGED_NOTIFY_ORCID_ORG, oldEmail, subject, body, html);
}
@Override
public void sendApiRecordCreationEmail(String toEmail, String orcid) {
OrcidProfile profile = orcidProfileCacheManager.retrieve(orcid);
sendApiRecordCreationEmail(toEmail, profile);
}
@Override
@Transactional
public void sendApiRecordCreationEmail(String toEmail, OrcidProfile createdProfile) {
Source source = null;
CustomEmailEntity customEmail = null;
if (createdProfile.getOrcidHistory() != null && createdProfile.getOrcidHistory().getSource() != null) {
if (!PojoUtil.isEmpty(createdProfile.getOrcidHistory().getSource().retrieveSourcePath())) {
source = createdProfile.getOrcidHistory().getSource();
customEmail = getCustomizedEmail(createdProfile.getOrcidHistory().getSource().retrieveSourcePath(), EmailType.CLAIM);
}
}
String email = createdProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue().trim();
String emailName = deriveEmailFriendlyName(createdProfile);
String orcid = createdProfile.getOrcidIdentifier().getPath();
String verificationUrl = createClaimVerificationUrl(email, orcidUrlManager.getBaseUrl());
String creatorName = "";
if (source != null) {
if (source.getSourceName() != null && source.getSourceName().getContent() != null) {
creatorName = source.getSourceName().getContent();
} else if (!PojoUtil.isEmpty(source.retrieveSourcePath())) {
creatorName = source.retrieveSourcePath();
}
}
String subject = null;
String body = null;
String htmlBody = null;
String sender = null;
if (customEmail != null) {
// Get the customized sender if available
sender = PojoUtil.isEmpty(customEmail.getSender()) ? CLAIM_NOTIFY_ORCID_ORG : customEmail.getSender();
// Get the customized subject is available
subject = PojoUtil.isEmpty(customEmail.getSubject()) ? getSubject("email.subject.api_record_creation", createdProfile) : customEmail.getSubject();
// Replace the wildcards
subject = subject.replace(WILDCARD_USER_NAME, emailName);
subject = subject.replace(WILDCARD_MEMBER_NAME, creatorName);
if (customEmail.isHtml()) {
htmlBody = customEmail.getContent();
htmlBody = htmlBody.replace(WILDCARD_USER_NAME, emailName);
htmlBody = htmlBody.replace(WILDCARD_MEMBER_NAME, creatorName);
htmlBody = htmlBody.replace(EmailConstants.WILDCARD_VERIFICATION_URL, verificationUrl);
if (htmlBody.contains(WILDCARD_WEBSITE) || htmlBody.contains(WILDCARD_DESCRIPTION)) {
ClientDetailsEntity clientDetails = customEmail.getClientDetailsEntity();
htmlBody = htmlBody.replace(WILDCARD_WEBSITE, clientDetails.getClientWebsite());
htmlBody = htmlBody.replace(WILDCARD_DESCRIPTION, clientDetails.getClientDescription());
}
} else {
body = customEmail.getContent();
body = body.replace(WILDCARD_USER_NAME, emailName);
body = body.replace(WILDCARD_MEMBER_NAME, creatorName);
body = body.replace(EmailConstants.WILDCARD_VERIFICATION_URL, verificationUrl);
if (body.contains(WILDCARD_WEBSITE) || body.contains(WILDCARD_DESCRIPTION)) {
ClientDetailsEntity clientDetails = customEmail.getClientDetailsEntity();
body = body.replace(WILDCARD_WEBSITE, clientDetails.getClientWebsite());
body = body.replace(WILDCARD_DESCRIPTION, clientDetails.getClientDescription());
}
}
} else {
subject = getSubject("email.subject.api_record_creation", createdProfile);
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", emailName);
templateParams.put("orcid", orcid);
templateParams.put("subject", subject);
templateParams.put("creatorName", creatorName);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("verificationUrl", verificationUrl);
addMessageParams(templateParams, createdProfile);
// Generate body from template
body = templateManager.processTemplate("api_record_creation_email.ftl", templateParams);
htmlBody = templateManager.processTemplate("api_record_creation_email_html.ftl", templateParams);
}
// Send message
if (apiRecordCreationEmailEnabled) {
boolean isCustomEmail = customEmail != null ? true : false;
// TODO: How to handle sender? we might have to register them on
// mailgun
if (isCustomEmail) {
mailGunManager.sendEmail(sender, email, subject, body, htmlBody, isCustomEmail);
} else {
mailGunManager.sendEmail(CLAIM_NOTIFY_ORCID_ORG, email, subject, body, htmlBody);
}
} else {
LOGGER.debug("Not sending API record creation email, because option is disabled. Message would have been: {}", body);
}
}
/**
* Returns a customized email for the given client and type
*
* @param source
* @param emailType
* @return a CustomEmailEntity if exists, null otherwise
*/
private CustomEmailEntity getCustomizedEmail(String source, EmailType emailType) {
return customEmailManager.getCustomEmail(source, emailType);
}
@Override
public void sendClaimReminderEmail(OrcidProfile orcidProfile, int daysUntilActivation) {
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", deriveEmailFriendlyName(orcidProfile));
String orcid = orcidProfile.getOrcidIdentifier().getPath();
templateParams.put("orcid", orcid);
templateParams.put("subject", getSubject("email.subject.claim_reminder", orcidProfile));
Source source = orcidProfile.getOrcidHistory().getSource();
String creatorName = "";
if (source != null) {
if (source.getSourceName() != null && source.getSourceName().getContent() != null) {
creatorName = source.getSourceName().getContent();
} else {
creatorName = source.retrieveSourcePath();
}
}
templateParams.put("creatorName", creatorName);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("daysUntilActivation", daysUntilActivation);
Email primaryEmail = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail();
if (primaryEmail == null) {
LOGGER.info("Cant send claim reminder email if primary email is null: {}", orcid);
return;
}
String verificationUrl = createClaimVerificationUrl(primaryEmail.getValue(), orcidUrlManager.getBaseUrl());
templateParams.put("verificationUrl", verificationUrl);
addMessageParams(templateParams, orcidProfile);
String email = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
// Generate body from template
String body = templateManager.processTemplate("claim_reminder_email.ftl", templateParams);
String htmlBody = templateManager.processTemplate("claim_reminder_email_html.ftl", templateParams);
// Send message
if (apiRecordCreationEmailEnabled) {
mailGunManager.sendEmail(CLAIM_NOTIFY_ORCID_ORG, email, getSubject("email.subject.claim_reminder", orcidProfile), body, htmlBody);
profileEventDao.persist(new ProfileEventEntity(orcid, ProfileEventType.CLAIM_REMINDER_SENT));
} else {
LOGGER.debug("Not sending claim reminder email, because API record creation email option is disabled. Message would have been: {}", body);
}
}
private String extractAmenderName(OrcidProfile orcidProfile, String amenderId) {
Delegation delegation = orcidProfile.getOrcidBio().getDelegation();
if (delegation != null && delegation.getGivenPermissionTo() != null && !delegation.getGivenPermissionTo().getDelegationDetails().isEmpty()) {
for (DelegationDetails delegationDetails : delegation.getGivenPermissionTo().getDelegationDetails()) {
if (amenderId.equals(delegationDetails.getDelegateSummary().getOrcidIdentifier().getPath())) {
return delegationDetails.getDelegateSummary().getCreditName().getContent();
}
}
}
ClientDetailsEntity clientDetailsEntity = clientDetailsEntityCacheManager.retrieve(amenderId);
if (clientDetailsEntity != null) {
return clientDetailsEntity.getClientName();
}
return "";
}
@Override
public String createClaimVerificationUrl(String email, String baseUri) {
return createEmailBaseUrl(email, baseUri, "claim");
}
public String createVerificationUrl(String email, String baseUri) {
return createEmailBaseUrl(email, baseUri, "verify-email");
}
private String createResetEmail(OrcidProfile orcidProfile, String baseUri) {
String resetParams = createResetParams(orcidProfile);
return createEmailBaseUrl(resetParams, baseUri, "reset-password-email");
}
private String createResetParams(OrcidProfile orcidProfile) {
String userEmail = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
return createResetParams(userEmail);
}
private String createResetParams(String userEmail) {
XMLGregorianCalendar date = DateUtils.convertToXMLGregorianCalendarNoTimeZoneNoMillis(new Date());
String resetParams = MessageFormat.format("email={0}&issueDate={1}", new Object[] { userEmail, date.toXMLFormat() });
return resetParams;
}
private String createReactivationUrl(String userEmail, String baseUri) {
String resetParams = createResetParams(userEmail);
return createEmailBaseUrl(resetParams, baseUri, "reactivation");
}
public String createEmailBaseUrl(String unencryptedParams, String baseUri, String path) {
// Encrypt and encode params
String encryptedUrlParams = encryptionManager.encryptForExternalUse(unencryptedParams);
String base64EncodedParams = null;
try {
base64EncodedParams = Base64.encodeBase64URLSafeString(encryptedUrlParams.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
return String.format("%s/%s/%s", baseUri, path, base64EncodedParams);
}
@Override
public void sendDelegationRequestEmail(String managedOrcid, String trustedOrcid, String link) {
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
templateParams.put("link", link);
ProfileEntity managedEntity = profileEntityCacheManager.retrieve(managedOrcid);
ProfileEntity trustedEntity = profileEntityCacheManager.retrieve(trustedOrcid);
String emailNameForDelegate = deriveEmailFriendlyName(managedEntity);
String trustedOrcidName = deriveEmailFriendlyName(trustedEntity);
templateParams.put("emailNameForDelegate", emailNameForDelegate);
templateParams.put("trustedOrcidName", trustedOrcidName);
templateParams.put("trustedOrcidValue", trustedOrcid);
templateParams.put("managedOrcidValue", managedOrcid);
String primaryEmail = emailManager.findPrimaryEmail(managedOrcid).getEmail();
if (primaryEmail == null) {
LOGGER.info("Cant send admin delegate email if primary email is null: {}", managedOrcid);
return;
}
org.orcid.jaxb.model.common_v2.Locale locale = managedEntity.getLocale();
Locale userLocale = LocaleUtils.toLocale("en");
if(locale != null) {
userLocale = LocaleUtils.toLocale(locale.value());
}
addMessageParams(templateParams, userLocale);
String htmlBody = templateManager.processTemplate("admin_delegate_request_html.ftl", templateParams);
// Send message
if (apiRecordCreationEmailEnabled) {
String subject = messages.getMessage("email.subject.admin_as_delegate", new Object[]{trustedOrcidName}, userLocale);
boolean notificationsEnabled = trustedEntity != null ? trustedEntity.getEnableNotifications() : false;
if (notificationsEnabled) {
NotificationCustom notification = new NotificationCustom();
notification.setNotificationType(NotificationType.CUSTOM);
notification.setSubject(subject);
notification.setBodyHtml(htmlBody);
createNotification(managedOrcid, notification);
} else {
mailGunManager.sendEmail(DELEGATE_NOTIFY_ORCID_ORG, primaryEmail, subject, null, htmlBody);
}
profileEventDao.persist(new ProfileEventEntity(managedOrcid, ProfileEventType.ADMIN_PROFILE_DELEGATION_REQUEST));
} else {
LOGGER.debug("Not sending admin delegate email, because API record creation email option is disabled. Message would have been: {}", htmlBody);
}
}
@Override
public Notification createNotification(String orcid, Notification notification) {
if (notification.getPutCode() != null) {
throw new IllegalArgumentException("Put code must be null when creating a new notification");
}
NotificationEntity notificationEntity = notificationAdapter.toNotificationEntity(notification);
ProfileEntity profile = profileEntityCacheManager.retrieve(orcid);
if (profile == null) {
throw OrcidNotFoundException.newInstance(orcid);
}
notificationEntity.setProfile(profile);
SourceEntity sourceEntity = sourceManager.retrieveSourceEntity();
if (sourceEntity != null) {
// Set source id
if (sourceEntity.getSourceProfile() != null) {
notificationEntity.setSourceId(sourceEntity.getSourceProfile().getId());
}
if (sourceEntity.getSourceClient() != null) {
notificationEntity.setClientSourceId(sourceEntity.getSourceClient().getId());
}
} else {
// If we can't find source id, set the user as the source
notificationEntity.setSourceId(orcid);
}
notificationDao.persist(notificationEntity);
return notificationAdapter.toNotification(notificationEntity);
}
@Override
public List<Notification> findUnsentByOrcid(String orcid) {
return notificationAdapter.toNotification(notificationDaoReadOnly.findUnsentByOrcid(orcid));
}
@Override
@Transactional(readOnly = true)
public List<Notification> findByOrcid(String orcid, boolean includeArchived, int firstResult, int maxResults) {
return notificationAdapter.toNotification(notificationDao.findByOrcid(orcid, includeArchived, firstResult, maxResults));
}
@Override
@Transactional(readOnly = true)
public NotificationPermissions findPermissionsByOrcidAndClient(String orcid, String client, int firstResult, int maxResults) {
NotificationPermissions notifications = new NotificationPermissions();
List<Notification> notificationsForOrcidAndClient = notificationAdapter
.toNotification(notificationDao.findPermissionsByOrcidAndClient(orcid, client, firstResult, maxResults));
List<NotificationPermission> notificationPermissions = new ArrayList<>();
notificationsForOrcidAndClient.forEach(n -> notificationPermissions.add((NotificationPermission) n));
notifications.setNotifications(notificationPermissions);
return notifications;
}
@Override
@Transactional(readOnly = true)
public List<Notification> findNotificationAlertsByOrcid(String orcid) {
return notificationAdapter.toNotification(notificationDao.findNotificationAlertsByOrcid(orcid));
}
@Override
public List<Notification> filterActionedNotificationAlerts(Collection<Notification> notifications, String userOrcid) {
return notifications.stream().filter(n -> {
//Filter only INSTITUTIONAL_CONNECTION notifications
if(NotificationType.INSTITUTIONAL_CONNECTION.equals(n.getNotificationType())) {
boolean alreadyConnected = orcidOauth2TokenDetailService.doesClientKnowUser(n.getSource().retrieveSourcePath(), userOrcid);
if (alreadyConnected) {
flagAsArchived(userOrcid, n.getPutCode(), false);
}
return !alreadyConnected;
}
return true;
}).collect(Collectors.toList());
}
@Override
@Transactional(readOnly = true)
public Notification findById(Long id) {
return notificationAdapter.toNotification(notificationDao.find(id));
}
@Override
@Transactional(readOnly = true)
public Notification findByOrcidAndId(String orcid, Long id) {
return notificationAdapter.toNotification(notificationDao.findByOricdAndId(orcid, id));
}
@Override
@Transactional
public Notification flagAsArchived(String orcid, Long id) throws OrcidNotificationAlreadyReadException {
return flagAsArchived(orcid, id, true);
}
@Override
@Transactional
public Notification flagAsArchived(String orcid, Long id, boolean validateForApi) throws OrcidNotificationAlreadyReadException {
NotificationEntity notificationEntity = notificationDao.findByOricdAndId(orcid, id);
if (notificationEntity == null) {
return null;
}
String sourceId = sourceManager.retrieveSourceOrcid();
if (validateForApi) {
if (sourceId != null && !sourceId.equals(notificationEntity.getElementSourceId())) {
Map<String, String> params = new HashMap<String, String>();
params.put("activity", "notification");
throw new WrongSourceException(params);
}
if (notificationEntity.getReadDate() != null) {
throw new OrcidNotificationAlreadyReadException();
}
}
if (notificationEntity.getArchivedDate() == null) {
notificationEntity.setArchivedDate(new Date());
notificationDao.merge(notificationEntity);
}
return notificationAdapter.toNotification(notificationEntity);
}
@Override
@Transactional
public Notification setActionedAndReadDate(String orcid, Long id) {
NotificationEntity notificationEntity = notificationDao.findByOricdAndId(orcid, id);
if (notificationEntity == null) {
return null;
}
Date now = new Date();
if (notificationEntity.getActionedDate() == null) {
notificationEntity.setActionedDate(now);
notificationDao.merge(notificationEntity);
}
if (notificationEntity.getReadDate() == null) {
notificationEntity.setReadDate(now);
notificationDao.merge(notificationEntity);
}
return notificationAdapter.toNotification(notificationEntity);
}
@Override
public void sendAcknowledgeMessage(String userOrcid, String clientId) throws UnsupportedEncodingException {
ProfileEntity profileEntity = profileEntityCacheManager.retrieve(userOrcid);
ClientDetailsEntity clientDetails = clientDetailsEntityCacheManager.retrieve(clientId);
Locale userLocale = (profileEntity.getLocale() == null || profileEntity.getLocale().value() == null) ? Locale.ENGLISH
: LocaleUtils.toLocale(profileEntity.getLocale().value());
String subject = getSubject("email.subject.institutional_sign_in", userLocale);
String authorizationUrl = buildAuthorizationUrlForInstitutionalSignIn(clientDetails);
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", deriveEmailFriendlyName(profileEntity));
templateParams.put("orcid", userOrcid);
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
templateParams.put("subject", subject);
templateParams.put("clientName", clientDetails.getClientName());
templateParams.put("authorization_url", authorizationUrl);
addMessageParams(templateParams, userLocale);
// Generate body from template
String body = templateManager.processTemplate("authenticate_request_email.ftl", templateParams);
// Generate html from template
String html = templateManager.processTemplate("authenticate_request_email_html.ftl", templateParams);
boolean notificationsEnabled = profileEntity.getEnableNotifications();
if (notificationsEnabled) {
NotificationInstitutionalConnection notification = new NotificationInstitutionalConnection();
notification.setNotificationType(NotificationType.INSTITUTIONAL_CONNECTION);
notification.setAuthorizationUrl(new AuthorizationUrl(authorizationUrl));
NotificationInstitutionalConnectionEntity notificationEntity = (NotificationInstitutionalConnectionEntity) notificationAdapter
.toNotificationEntity(notification);
notificationEntity.setProfile(new ProfileEntity(userOrcid));
notificationEntity.setClientSourceId(clientId);
notificationEntity.setAuthenticationProviderId(clientDetails.getAuthenticationProviderId());
notificationDao.persist(notificationEntity);
} else {
Emails emails = emailManager.getEmails(userOrcid,
(profileEntity.getLastModified() == null ? System.currentTimeMillis() : profileEntity.getLastModified().getTime()));
String primaryEmail = null;
if (emails == null || emails.getEmails() == null) {
throw new IllegalArgumentException("Unable to find primary email for: " + userOrcid);
}
for (org.orcid.jaxb.model.record_v2.Email email : emails.getEmails()) {
if (email.isPrimary()) {
primaryEmail = email.getEmail();
}
}
mailGunManager.sendEmail(UPDATE_NOTIFY_ORCID_ORG, primaryEmail, subject, body, html);
}
}
public String buildAuthorizationUrlForInstitutionalSignIn(ClientDetailsEntity clientDetails) throws UnsupportedEncodingException {
ClientRedirectUriEntity rUri = getRedirectUriForInstitutionalSignIn(clientDetails);
if (rUri == null) {
return null;
}
String urlEncodedScopes = URLEncoder.encode(rUri.getPredefinedClientScope(), "UTF-8");
String urlEncodedRedirectUri = URLEncoder.encode(rUri.getRedirectUri(), "UTF-8");
return MessageFormat.format(AUTHORIZATION_END_POINT, orcidUrlManager.getBaseUrl(), clientDetails.getClientId(), urlEncodedScopes, urlEncodedRedirectUri);
}
private ClientRedirectUriEntity getRedirectUriForInstitutionalSignIn(ClientDetailsEntity clientDetails) {
if (clientDetails == null) {
throw new IllegalArgumentException("Unable to find valid redirect uris for null client details");
}
if (clientDetails.getClientRegisteredRedirectUris() == null) {
throw new IllegalArgumentException("Unable to find valid redirect uris for client: " + clientDetails.getId());
}
ClientRedirectUriEntity result = null;
// Look for the redirect uri of INSTITUTIONAL_SIGN_IN type or if none if
// found, return the first DEFAULT one
for (ClientRedirectUriEntity redirectUri : clientDetails.getClientRegisteredRedirectUris()) {
if (RedirectUriType.INSTITUTIONAL_SIGN_IN.value().equals(redirectUri.getRedirectUriType())) {
result = redirectUri;
break;
}
}
return result;
}
@Override
public void sendAutoDeprecateNotification(String primaryOrcid, String deprecatedOrcid) {
ProfileEntity primaryProfileEntity = profileEntityCacheManager.retrieve(primaryOrcid);
ProfileEntity deprecatedProfileEntity = profileEntityCacheManager.retrieve(deprecatedOrcid);
ClientDetailsEntity clientDetails = clientDetailsEntityCacheManager.retrieve(deprecatedProfileEntity.getSource().getSourceId());
Locale userLocale = LocaleUtils
.toLocale(primaryProfileEntity.getLocale() == null ? org.orcid.jaxb.model.message.Locale.EN.value() : primaryProfileEntity.getLocale().value());
// Create map of template params
Map<String, Object> templateParams = new HashMap<String, Object>();
String subject = getSubject("email.subject.auto_deprecate", userLocale);
String baseUri = orcidUrlManager.getBaseUrl();
Date deprecatedAccountCreationDate = deprecatedProfileEntity.getDateCreated();
// Create map of template params
templateParams.put("primaryId", primaryOrcid);
templateParams.put("name", deriveEmailFriendlyName(primaryProfileEntity));
templateParams.put("baseUri", baseUri);
templateParams.put("subject", subject);
templateParams.put("clientName", clientDetails.getClientName());
templateParams.put("deprecatedAccountCreationDate", deprecatedAccountCreationDate);
templateParams.put("deprecatedId", deprecatedOrcid);
addMessageParams(templateParams, userLocale);
// Generate html from template
String html = templateManager.processTemplate("auto_deprecated_account_html.ftl", templateParams);
NotificationCustom notification = new NotificationCustom();
notification.setNotificationType(NotificationType.CUSTOM);
notification.setSubject(subject);
notification.setBodyHtml(html);
createNotification(primaryOrcid, notification);
}
public int getUnreadCount(String orcid) {
return notificationDao.getUnreadCount(orcid);
}
@Override
public void flagAsRead(String orcid, Long id) {
notificationDao.flagAsRead(orcid, id);
}
@Override
public ActionableNotificationEntity findActionableNotificationEntity(Long id) {
return (ActionableNotificationEntity) notificationDao.find(id);
}
public boolean sendVerifiedRequiredAnnouncement2017(OrcidProfile orcidProfile) {
String email = orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
String emailFriendlyName = deriveEmailFriendlyName(orcidProfile);
String verificationUrl = createVerificationUrl(email, orcidUrlManager.getBaseUrl());
String emailFrequencyUrl = createUpdateEmailFrequencyUrl(orcidProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue());
Map<String, Object> templateParams = new HashMap<String, Object>();
templateParams.put("emailName", emailFriendlyName);
templateParams.put("verificationUrl", verificationUrl);
templateParams.put("emailFrequencyUrl", emailFrequencyUrl);
templateParams.put("orcid", orcidProfile.getOrcidIdentifier().getPath());
templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
addMessageParams(templateParams, orcidProfile);
String subject = getSubject("email.service_announcement.subject.imporant_information", orcidProfile);
String text = templateManager.processTemplate("verified_required_announcement_2017.ftl", templateParams);
String html = templateManager.processTemplate("verified_required_announcement_2017_html.ftl", templateParams);
return mailGunManager.sendEmail("support@notify.orcid.org", email, subject, text, html);
}
private Locale getUserLocaleFromProfileEntity(ProfileEntity profile) {
org.orcid.jaxb.model.common_v2.Locale locale = profile.getLocale();
if (locale != null) {
return LocaleUtils.toLocale(locale.value());
}
return LocaleUtils.toLocale("en");
}
}