• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #23250

25 Sep 2024 03:43PM UTC coverage: 20.873%. First build
#23250

Pull #10781

github

web-flow
Merge 682c89fc0 into ea0247887
Pull Request #10781: Improved handling of Globus uploads (experimental async framework)

4 of 417 new or added lines in 15 files covered. (0.96%)

17967 of 86079 relevant lines covered (20.87%)

0.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

13.13
/src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java
1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package edu.harvard.iq.dataverse;
7

8
import edu.harvard.iq.dataverse.authorization.groups.Group;
9
import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean;
10
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
11
import edu.harvard.iq.dataverse.branding.BrandingUtil;
12
import edu.harvard.iq.dataverse.confirmemail.ConfirmEmailServiceBean;
13
import edu.harvard.iq.dataverse.dataset.DatasetUtil;
14
import edu.harvard.iq.dataverse.settings.JvmSettings;
15
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
16
import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key;
17
import edu.harvard.iq.dataverse.util.BundleUtil;
18
import edu.harvard.iq.dataverse.util.MailUtil;
19
import edu.harvard.iq.dataverse.util.SystemConfig;
20
import edu.harvard.iq.dataverse.util.json.JsonUtil;
21

22
import java.io.UnsupportedEncodingException;
23
import java.text.MessageFormat;
24
import java.util.ArrayList;
25
import java.util.Arrays;
26
import java.util.Date;
27
import java.util.List;
28
import java.util.Objects;
29
import java.util.Optional;
30
import java.util.Set;
31
import java.util.logging.Level;
32
import java.util.logging.Logger;
33
import jakarta.ejb.EJB;
34
import jakarta.ejb.Stateless;
35
import jakarta.inject.Inject;
36
import jakarta.inject.Named;
37
import jakarta.mail.Address;
38
import jakarta.mail.Message;
39
import jakarta.mail.MessagingException;
40
import jakarta.mail.Session;
41
import jakarta.mail.Transport;
42
import jakarta.mail.internet.AddressException;
43
import jakarta.mail.internet.InternetAddress;
44
import jakarta.mail.internet.MimeMessage;
45

46
import edu.harvard.iq.dataverse.validation.EMailValidator;
47
import jakarta.json.JsonObject;
48
import org.apache.commons.lang3.StringUtils;
49

50
/**
51
 *
52
 * original author: roberttreacy
53
 */
54
@Stateless
55
public class MailServiceBean implements java.io.Serializable {
56
    @EJB
57
    UserNotificationServiceBean userNotificationService;
58
    @EJB
59
    DataverseServiceBean dataverseService;
60
    @EJB
61
    DataFileServiceBean dataFileService;
62
    @EJB
63
    DatasetServiceBean datasetService;
64
    @EJB
65
    DatasetVersionServiceBean versionService; 
66
    @EJB
67
    SystemConfig systemConfig;
68
    @EJB
69
    SettingsServiceBean settingsService;
70
    @EJB
71
    PermissionServiceBean permissionService;
72
    @EJB
73
    GroupServiceBean groupService;
74
    @EJB
75
    ConfirmEmailServiceBean confirmEmailService;
76

77
    private static final Logger logger = Logger.getLogger(MailServiceBean.class.getCanonicalName());
1✔
78

79
    private static final String charset = "UTF-8";
80

81
    /**
82
     * Creates a new instance of MailServiceBean
83
     */
84
    public MailServiceBean() {
1✔
85
    }
1✔
86
    
87
    /**
88
     * Creates a new instance of MailServiceBean with explicit injection, as used during testing.
89
     */
90
    public MailServiceBean(Session session, SettingsServiceBean settingsService) {
1✔
91
        this.session = session;
1✔
92
        this.settingsService = settingsService;
1✔
93
    }
1✔
94

95
    @Inject
96
    @Named("mail/systemSession")
97
    private Session session;
98

99
    public boolean sendSystemEmail(String to, String subject, String messageText) {
100
        return sendSystemEmail(to, subject, messageText, false);
×
101
    }
102
    
103
    /**
104
     * Send a system notification to one or multiple recipients by email.
105
     * Will skip sending when {@link #getSystemAddress()} doesn't return a configured "from" address.
106
     * @param to A comma separated list of one or multiple recipients' addresses. May contain a "personal name" and
107
     *           the recipients address in <>. See also {@link InternetAddress}.
108
     * @param subject The message's subject
109
     * @param messageText The message's text
110
     * @param isHtmlContent Determine if the message text is formatted using HTML or plain text.
111
     * @return Status: true if sent successfully, false otherwise
112
     */
113
    public boolean sendSystemEmail(String to, String subject, String messageText, boolean isHtmlContent) {
114
        Optional<InternetAddress> optionalAddress = getSystemAddress();
1✔
115
        if (optionalAddress.isEmpty()) {
1✔
116
            logger.fine(() -> "Skipping sending mail to " + to + ", because no system address has been set.");
1✔
117
            return false;
1✔
118
        }
119
        InternetAddress systemAddress = optionalAddress.get();
1✔
120
        InternetAddress supportAddress = getSupportAddress().orElse(systemAddress);
1✔
121

122
        String body = messageText +
1✔
123
            BundleUtil.getStringFromBundle(isHtmlContent ? "notification.email.closing.html" : "notification.email.closing",
1✔
124
                List.of(BrandingUtil.getSupportTeamEmailAddress(supportAddress), BrandingUtil.getSupportTeamName(supportAddress)));
1✔
125

126
        logger.fine(() -> "Sending email to %s. Subject: <<<%s>>>. Body: %s".formatted(to, subject, body));
1✔
127
        try {
128
            // Since JavaMail 1.6, we have support for UTF-8 mail addresses and do not need to handle these ourselves.
129
            InternetAddress[] recipients = InternetAddress.parse(to);
1✔
130
            
131
            MimeMessage msg = new MimeMessage(session);
1✔
132
            msg.setFrom(systemAddress);
1✔
133
            msg.setSentDate(new Date());
1✔
134
            msg.setRecipients(Message.RecipientType.TO, recipients);
1✔
135
            msg.setSubject(subject, charset);
1✔
136
            if (isHtmlContent) {
1✔
137
                msg.setText(body, charset, "html");
×
138
            } else {
139
                msg.setText(body, charset);
1✔
140
            }
141
            
142
            Transport.send(msg, recipients);
1✔
143
            return true;
1✔
144
        } catch (MessagingException ae) {
1✔
145
            logger.log(Level.WARNING, "Failed to send mail to %s: %s".formatted(to, ae.getMessage()), ae);
1✔
146
            logger.info("When UTF-8 characters in recipients: make sure MTA supports it and JVM option " + JvmSettings.MAIL_MTA_SUPPORT_UTF8.getScopedKey() + "=true");
1✔
147
        }
148
        return false;
1✔
149
    }
150
    
151
    /**
152
     * Lookup the system mail address ({@code InternetAddress} may contain personal and actual address).
153
     * @return The system mail address or an empty {@code Optional} if not configured.
154
     */
155
    public Optional<InternetAddress> getSystemAddress() {
156
        boolean providedByDB = false;
1✔
157
        String mailAddress = JvmSettings.SYSTEM_EMAIL.lookupOptional().orElse(null);
1✔
158
        
159
        // Try lookup of (deprecated) database setting only if not configured via MPCONFIG
160
        if (mailAddress == null) {
1✔
161
            mailAddress = settingsService.getValueForKey(Key.SystemEmail);
1✔
162
            // Encourage people to migrate from deprecated setting
163
            if (mailAddress != null) {
1✔
164
                providedByDB = true;
1✔
165
                logger.warning("The :SystemMail DB setting has been deprecated, please reconfigure using JVM option " + JvmSettings.SYSTEM_EMAIL.getScopedKey());
1✔
166
            }
167
        }
168
        
169
        try {
170
            // Parse and return.
171
            return Optional.of(new InternetAddress(Objects.requireNonNull(mailAddress), true));
1✔
172
        } catch (AddressException e) {
×
173
            logger.log(Level.WARNING, "Could not parse system mail address '%s' provided by %s: "
×
174
                .formatted(providedByDB ? "DB setting" : "JVM option", mailAddress), e);
×
175
        } catch (NullPointerException e) {
1✔
176
            // Do not pester the logs - no configuration may mean someone wants to disable mail notifications
177
            logger.fine("Could not find a system mail setting in database (key :SystemEmail, deprecated) or JVM option '" + JvmSettings.SYSTEM_EMAIL.getScopedKey() + "'");
1✔
178
        }
×
179
        // We define the system email address as an optional setting, in case people do not want to enable mail
180
        // notifications (like in a development context, but might be useful elsewhere, too).
181
        return Optional.empty();
1✔
182
    }
183
    
184
    /**
185
     * Lookup the support team mail address ({@code InternetAddress} may contain personal and actual address).
186
     * Will default to return {@code #getSystemAddress} if not configured.
187
     * @return Support team mail address
188
     */
189
    public Optional<InternetAddress> getSupportAddress() {
190
        Optional<String> supportMailAddress = JvmSettings.SUPPORT_EMAIL.lookupOptional();
1✔
191
        if (supportMailAddress.isPresent()) {
1✔
192
            try {
193
                return Optional.of(new InternetAddress(supportMailAddress.get(), true));
1✔
194
            } catch (AddressException e) {
×
195
                logger.log(Level.WARNING, "Could not parse support mail address '%s', defaulting to system address: ".formatted(supportMailAddress.get()), e);
×
196
            }
197
        }
198
        return getSystemAddress();
1✔
199
    }
200

201
    //@Resource(name="mail/notifyMailSession")
202
    public void sendMail(String reply, String to, String cc, String subject, String messageText) {
203
        Optional<InternetAddress> optionalAddress = getSystemAddress();
×
204
        if (optionalAddress.isEmpty()) {
×
205
            logger.fine(() -> "Skipping sending mail to " + to + ", because no system address has been set.");
×
206
            return;
×
207
        }
208
        // Always send from system address to avoid email being blocked
209
        InternetAddress fromAddress = optionalAddress.get();
×
210
        
211
        try {
212
            MimeMessage msg = new MimeMessage(session);
×
213
            
214
            try {
215
                setContactDelegation(reply, fromAddress);
×
216
            } catch (UnsupportedEncodingException ex) {
×
217
                logger.severe(ex.getMessage());
×
218
            }
×
219
            msg.setFrom(fromAddress);
×
220
            if (EMailValidator.isEmailValid(reply)) {
×
221
                    // But set the reply-to address to direct replies to the requested 'from' party if it is a valid email address
222
                msg.setReplyTo(new Address[] {new InternetAddress(reply)});
×
223
            } else {
224
                // Otherwise include the invalid 'from' address in the message
225
                messageText = "From: " + reply + "\n\n" + messageText;
×
226
            }
227
            msg.setSentDate(new Date());
×
228
            msg.setRecipients(Message.RecipientType.TO,
×
229
                    InternetAddress.parse(to, false));
×
230
            if (cc != null) {
×
231
                msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc, false));
×
232
            }
233
            msg.setSubject(subject, charset);
×
234
            msg.setText(messageText, charset);
×
235

236
            Transport.send(msg);
×
237
        } catch (AddressException ae) {
×
238
            ae.printStackTrace(System.out);
×
239
        } catch (MessagingException me) {
×
240
            me.printStackTrace(System.out);
×
241
        }
×
242
    }
×
243

244
    /**
245
     * Set the contact delegation as "[dataverse team] on behalf of [user email]"
246
     * @param reply The user's email address as give via the contact form
247
     * @param fromAddress The system email address
248
     * @throws UnsupportedEncodingException
249
     */
250
    public void setContactDelegation(String reply, InternetAddress fromAddress)
251
            throws UnsupportedEncodingException {
252
        String personal = fromAddress.getPersonal() != null
1✔
253
            ? fromAddress.getPersonal()
1✔
254
            : BrandingUtil.getInstallationBrandName() != null
1✔
255
                ? BrandingUtil.getInstallationBrandName()
1✔
256
                : BundleUtil.getStringFromBundle("contact.delegation.default_personal");
1✔
257
        fromAddress.setPersonal(
1✔
258
            BundleUtil.getStringFromBundle(
1✔
259
                "contact.delegation",
260
                Arrays.asList(personal, reply)),
1✔
261
            charset
262
        );
263
    }
1✔
264

265
    public Boolean sendNotificationEmail(UserNotification notification){
266
        return sendNotificationEmail(notification, "");
×
267
    }
268

269
    public Boolean sendNotificationEmail(UserNotification notification, String comment) {
270
        return sendNotificationEmail(notification, comment, null, false);
×
271
    }
272

273
    public Boolean sendNotificationEmail(UserNotification notification, String comment, boolean isHtmlContent) {
274
        return sendNotificationEmail(notification, comment, null, isHtmlContent);
×
275
    }
276

277
    public Boolean sendNotificationEmail(UserNotification notification, String comment, AuthenticatedUser requestor, boolean isHtmlContent){
278

279
        boolean retval = false;
×
280
        String emailAddress = getUserEmailAddress(notification);
×
281
        if (emailAddress != null){
×
282
           Object objectOfNotification =  getObjectOfNotification(notification);
×
283
           if (objectOfNotification != null){
×
284
               String messageText = getMessageTextBasedOnNotification(notification, objectOfNotification, comment, requestor);
×
285
               String subjectText = MailUtil.getSubjectTextBasedOnNotification(notification, objectOfNotification);
×
286
               if (!(messageText.isEmpty() || subjectText.isEmpty())){
×
287
                   retval = sendSystemEmail(emailAddress, subjectText, messageText, isHtmlContent);
×
288
               } else {
289
                   logger.warning("Skipping " + notification.getType() +  " notification, because couldn't get valid message");
×
290
               }
291
           } else { 
×
292
               logger.warning("Skipping " + notification.getType() +  " notification, because no valid Object was found");
×
293
           }           
294
        } else {
×
295
            logger.warning("Skipping " + notification.getType() +  " notification, because email address is null");
×
296
        }
297
        return retval;
×
298
    }
299

300
    private String getDatasetManageFileAccessLink(DataFile datafile){
301
        return  systemConfig.getDataverseSiteUrl() + "/permissions-manage-files.xhtml?id=" + datafile.getOwner().getId();
×
302
    } 
303

304
    private String getDatasetLink(Dataset dataset){        
305
        return  systemConfig.getDataverseSiteUrl() + "/dataset.xhtml?persistentId=" + dataset.getGlobalId().asString();
×
306
    } 
307

308
    private String getDatasetDraftLink(Dataset dataset){        
309
        return  systemConfig.getDataverseSiteUrl() + "/dataset.xhtml?persistentId=" + dataset.getGlobalId().asString() + "&version=DRAFT" + "&faces-redirect=true"; 
×
310
    } 
311

312
    private String getDataverseLink(Dataverse dataverse){       
313
        return  systemConfig.getDataverseSiteUrl() + "/dataverse/" + dataverse.getAlias();
×
314
    }
315

316
    /**
317
     * Returns a '/'-separated string of roles that are effective for {@code au}
318
     * over {@code dvObj}. Traverses the containment hierarchy of the {@code d}.
319
     * Takes into consideration all groups that {@code au} is part of.
320
     * @param au The authenticated user whose role assignments we look for.
321
     * @param dvObj The Dataverse object over which the roles are assigned
322
     * @return A set of all the role assignments for {@code ra} over {@code d}.
323
     */
324
    private String getRoleStringFromUser(AuthenticatedUser au, DvObject dvObj) {
325
        // Find user's role(s) for given dataverse/dataset
326
        Set<RoleAssignment> roles = permissionService.assignmentsFor(au, dvObj);
×
327
        List<String> roleNames = new ArrayList<>();
×
328

329
        // Include roles derived from a user's groups
330
        Set<Group> groupsUserBelongsTo = groupService.groupsFor(au, dvObj);
×
331
        for (Group g : groupsUserBelongsTo) {
×
332
            roles.addAll(permissionService.assignmentsFor(g, dvObj));
×
333
        }
×
334

335
        for (RoleAssignment ra : roles) {
×
336
            roleNames.add(ra.getRole().getName());
×
337
        }
×
338
        return StringUtils.join(roleNames, "/");
×
339
    }
340

341
    /**
342
     * Returns the URL to a given {@code DvObject} {@code d}. If {@code d} is a
343
     * {@code DataFile}, return a link to its {@code DataSet}.
344
     * @param d The Dataverse object to get a link for.
345
     * @return A string with a URL to the given Dataverse object.
346
     */
347
    private String getDvObjectLink(DvObject d) {
348
        if (d instanceof Dataverse) {
×
349
            return getDataverseLink((Dataverse) d);
×
350
        } else if (d instanceof Dataset) {
×
351
            return getDatasetLink((Dataset) d);
×
352
        } else if (d instanceof DataFile) {
×
353
            return getDatasetLink(((DataFile) d).getOwner());
×
354
        }
355
        return "";
×
356
    }
357

358
    /**
359
     * Returns string representation of the type of {@code DvObject} {@code d}.
360
     * @param d The Dataverse object to get the string for
361
     * @return A string that represents the type of a given Dataverse object.
362
     */
363
    private String getDvObjectTypeString(DvObject d) {
364
        if (d instanceof Dataverse) {
×
365
            return "dataverse";
×
366
        } else if (d instanceof Dataset) {
×
367
            return "dataset";
×
368
        } else if (d instanceof DataFile) {
×
369
            return "data file";
×
370
        }
371
        return "";
×
372
    }
373

374
    public String getMessageTextBasedOnNotification(UserNotification userNotification, Object targetObject){
375
        return getMessageTextBasedOnNotification(userNotification, targetObject, "");
×
376
    }
377

378
    public String getMessageTextBasedOnNotification(UserNotification userNotification, Object targetObject, String comment) {
379
        return getMessageTextBasedOnNotification(userNotification, targetObject, comment, null);
×
380
    }
381

382
    public String getMessageTextBasedOnNotification(UserNotification userNotification, Object targetObject, String comment, AuthenticatedUser requestor) {
383
        String messageText = BundleUtil.getStringFromBundle("notification.email.greeting");
×
384
        DatasetVersion version;
385
        Dataset dataset;
386
        DvObject dvObj;
387
        String dvObjURL;
388
        String dvObjTypeStr;
389
        String pattern;
390

391
        switch (userNotification.getType()) {
×
392
            case ASSIGNROLE:
393
                AuthenticatedUser au = userNotification.getUser();
×
394
                dvObj = (DvObject) targetObject;
×
395

396
                String joinedRoleNames = getRoleStringFromUser(au, dvObj);
×
397

398
                dvObjURL = getDvObjectLink(dvObj);
×
399
                dvObjTypeStr = getDvObjectTypeString(dvObj);
×
400

401
                pattern = BundleUtil.getStringFromBundle("notification.email.assignRole");
×
402
                String[] paramArrayAssignRole = {joinedRoleNames, dvObjTypeStr, dvObj.getDisplayName(), dvObjURL};
×
403
                messageText += MessageFormat.format(pattern, paramArrayAssignRole);
×
404
                if (joinedRoleNames.contains("File Downloader")){
×
405
                    if (dvObjTypeStr.equals("dataset")){
×
406
                         pattern = BundleUtil.getStringFromBundle("notification.access.granted.fileDownloader.additionalDataset");
×
407
                         String[]  paramArrayAssignRoleDS = {" "};
×
408
                        messageText += MessageFormat.format(pattern, paramArrayAssignRoleDS);
×
409
                    }
410
                    if (dvObjTypeStr.equals("dataverse")){
×
411
                        pattern = BundleUtil.getStringFromBundle("notification.access.granted.fileDownloader.additionalDataverse");
×
412
                         String[]  paramArrayAssignRoleDV = {" "};
×
413
                        messageText += MessageFormat.format(pattern, paramArrayAssignRoleDV);
×
414
                    }                   
415
                }
416
                return messageText;
×
417
            case REVOKEROLE:
418
                dvObj = (DvObject) targetObject;
×
419

420
                dvObjURL = getDvObjectLink(dvObj);
×
421
                dvObjTypeStr = getDvObjectTypeString(dvObj);
×
422

423
                pattern = BundleUtil.getStringFromBundle("notification.email.revokeRole");
×
424
                String[] paramArrayRevokeRole = {dvObjTypeStr, dvObj.getDisplayName(), dvObjURL};
×
425
                messageText += MessageFormat.format(pattern, paramArrayRevokeRole);
×
426
                return messageText;
×
427
            case CREATEDV:
428
                Dataverse dataverse = (Dataverse) targetObject;
×
429
                Dataverse parentDataverse = dataverse.getOwner();
×
430
                // initialize to empty string in the rare case that there is no parent dataverse (i.e. root dataverse just created)
431
                String parentDataverseDisplayName = "";
×
432
                String parentDataverseUrl = "";
×
433
                if (parentDataverse != null) {
×
434
                    parentDataverseDisplayName = parentDataverse.getDisplayName();
×
435
                    parentDataverseUrl = getDataverseLink(parentDataverse);
×
436
                }
437
                String dataverseCreatedMessage = BundleUtil.getStringFromBundle("notification.email.createDataverse", Arrays.asList(
×
438
                        dataverse.getDisplayName(),
×
439
                        getDataverseLink(dataverse),
×
440
                        parentDataverseDisplayName,
441
                        parentDataverseUrl,
442
                        systemConfig.getGuidesBaseUrl(),
×
443
                        systemConfig.getGuidesVersion()));
×
444
                logger.fine(dataverseCreatedMessage);
×
445
                return messageText += dataverseCreatedMessage;
×
446
            case REQUESTFILEACCESS:
447
                //Notification to those who can grant file access requests on a dataset when a user makes a request
448
                DataFile datafile = (DataFile) targetObject;
×
449
                
450
                pattern = BundleUtil.getStringFromBundle("notification.email.requestFileAccess");
×
451
                String requestorName = (requestor.getLastName() != null && requestor.getLastName() != null) ? requestor.getFirstName() + " " + requestor.getLastName() : BundleUtil.getStringFromBundle("notification.email.info.unavailable");
×
452
                String requestorEmail = requestor.getEmail() != null ? requestor.getEmail() : BundleUtil.getStringFromBundle("notification.email.info.unavailable"); 
×
453
                String[] paramArrayRequestFileAccess = {datafile.getOwner().getDisplayName(), requestorName, requestorEmail, getDatasetManageFileAccessLink(datafile)};
×
454
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
455
                messageText += MessageFormat.format(pattern, paramArrayRequestFileAccess);
×
456
                FileAccessRequest far = datafile.getAccessRequestForAssignee(requestor);
×
457
                GuestbookResponse gbr = far.getGuestbookResponse();
×
458
                if (gbr != null) {
×
459
                    messageText += MessageFormat.format(
×
460
                        BundleUtil.getStringFromBundle("notification.email.requestFileAccess.guestbookResponse"), gbr.toHtmlFormattedResponse(requestor));
×
461
                }
462
                return messageText;
×
463
            case GRANTFILEACCESS:
464
                dataset = (Dataset) targetObject;
×
465
                pattern = BundleUtil.getStringFromBundle("notification.email.grantFileAccess");
×
466
                String[] paramArrayGrantFileAccess = {dataset.getDisplayName(), getDatasetLink(dataset)};
×
467
                messageText += MessageFormat.format(pattern, paramArrayGrantFileAccess);
×
468
                return messageText;
×
469
            case REJECTFILEACCESS:
470
                dataset = (Dataset) targetObject;
×
471
                pattern = BundleUtil.getStringFromBundle("notification.email.rejectFileAccess");
×
472
                String[] paramArrayRejectFileAccess = {dataset.getDisplayName(), getDatasetLink(dataset)};
×
473
                messageText += MessageFormat.format(pattern, paramArrayRejectFileAccess);
×
474
                return messageText;
×
475
            case DATASETCREATED:
476
                dataset = (Dataset) targetObject;
×
477
                pattern = BundleUtil.getStringFromBundle("notification.email.datasetWasCreated");
×
478
                String[] paramArrayDatasetCreated = {getDatasetLink(dataset), dataset.getDisplayName(), userNotification.getRequestor().getName(), dataset.getOwner().getDisplayName()};
×
479
                messageText += MessageFormat.format(pattern, paramArrayDatasetCreated);
×
480
                return messageText;
×
481
            case CREATEDS:
482
                version =  (DatasetVersion) targetObject;
×
483
                String datasetCreatedMessage = BundleUtil.getStringFromBundle("notification.email.createDataset", Arrays.asList(
×
484
                        version.getDataset().getDisplayName(),
×
485
                        getDatasetLink(version.getDataset()),
×
486
                        version.getDataset().getOwner().getDisplayName(),
×
487
                        getDataverseLink(version.getDataset().getOwner()),
×
488
                        systemConfig.getGuidesBaseUrl(),
×
489
                        systemConfig.getGuidesVersion()
×
490
                ));
491
                logger.fine(datasetCreatedMessage);
×
492
                return messageText += datasetCreatedMessage;
×
493
            case SUBMITTEDDS:
494
                version =  (DatasetVersion) targetObject;
×
495
                String mightHaveSubmissionComment = "";              
×
496
                /*
497
                FIXME
498
                Setting up to add single comment when design completed
499
                "submissionComment" needs to be added to Bundle
500
                mightHaveSubmissionComment = ".";
501
                if (comment != null && !comment.isEmpty()) {
502
                    mightHaveSubmissionComment = ".\n\n" + BundleUtil.getStringFromBundle("submissionComment") + "\n\n" + comment;
503
                }
504
                */                
505
                 requestorName = (requestor.getLastName() != null && requestor.getLastName() != null) ? requestor.getFirstName() + " " + requestor.getLastName() : BundleUtil.getStringFromBundle("notification.email.info.unavailable");
×
506
                 requestorEmail = requestor.getEmail() != null ? requestor.getEmail() : BundleUtil.getStringFromBundle("notification.email.info.unavailable");               
×
507
                pattern = BundleUtil.getStringFromBundle("notification.email.wasSubmittedForReview");
×
508

509
                String[] paramArraySubmittedDataset = {version.getDataset().getDisplayName(), getDatasetDraftLink(version.getDataset()), 
×
510
                    version.getDataset().getOwner().getDisplayName(),  getDataverseLink(version.getDataset().getOwner()),
×
511
                   requestorName, requestorEmail  };
512
                messageText += MessageFormat.format(pattern, paramArraySubmittedDataset);
×
513
                return messageText;
×
514
            case PUBLISHEDDS:
515
                version =  (DatasetVersion) targetObject;
×
516
                pattern = BundleUtil.getStringFromBundle("notification.email.wasPublished");
×
517
                String[] paramArrayPublishedDataset = {version.getDataset().getDisplayName(), getDatasetLink(version.getDataset()), 
×
518
                    version.getDataset().getOwner().getDisplayName(),  getDataverseLink(version.getDataset().getOwner())};
×
519
                messageText += MessageFormat.format(pattern, paramArrayPublishedDataset);
×
520
                return messageText;
×
521
            case PUBLISHFAILED_PIDREG:
522
                version =  (DatasetVersion) targetObject;
×
523
                pattern = BundleUtil.getStringFromBundle("notification.email.publishFailedPidReg");
×
524
                String[] paramArrayPublishFailedDatasetPidReg = {version.getDataset().getDisplayName(), getDatasetLink(version.getDataset()), 
×
525
                    version.getDataset().getOwner().getDisplayName(),  getDataverseLink(version.getDataset().getOwner())};
×
526
                messageText += MessageFormat.format(pattern, paramArrayPublishFailedDatasetPidReg);
×
527
                return messageText;
×
528
            case RETURNEDDS:
529
                version =  (DatasetVersion) targetObject;
×
530
                pattern = BundleUtil.getStringFromBundle("notification.email.wasReturnedByReviewer");
×
531

532
                String[] paramArrayReturnedDataset = {version.getDataset().getDisplayName(), getDatasetDraftLink(version.getDataset()), 
×
533
                    version.getDataset().getOwner().getDisplayName(),  getDataverseLink(version.getDataset().getOwner())};
×
534
                messageText += MessageFormat.format(pattern, paramArrayReturnedDataset);
×
535

536
                if (comment != null && !comment.isEmpty()) {
×
537
                    messageText += "\n\n" + MessageFormat.format(BundleUtil.getStringFromBundle("notification.email.wasReturnedByReviewerReason"), comment);
×
538
                }
539

540
                Dataverse d = (Dataverse) version.getDataset().getOwner();
×
541
                List<String> contactEmailList = new ArrayList<String>();
×
542
                for (DataverseContact dc : d.getDataverseContacts()) {
×
543
                    contactEmailList.add(dc.getContactEmail());
×
544
                }
×
545
                if (!contactEmailList.isEmpty()) {
×
546
                    String contactEmails = String.join(", ", contactEmailList);
×
547
                    messageText += "\n\n" + MessageFormat.format(BundleUtil.getStringFromBundle("notification.email.wasReturnedByReviewer.collectionContacts"), contactEmails);
×
548
                }
549
                return messageText;
×
550

551
            case WORKFLOW_SUCCESS:
552
                version =  (DatasetVersion) targetObject;
×
553
                pattern = BundleUtil.getStringFromBundle("notification.email.workflow.success");
×
554
                if (comment == null) {
×
555
                    comment = BundleUtil.getStringFromBundle("notification.email.workflow.nullMessage");
×
556
                }
557
                String[] paramArrayWorkflowSuccess = {version.getDataset().getDisplayName(), getDatasetLink(version.getDataset()), comment};
×
558
                messageText += MessageFormat.format(pattern, paramArrayWorkflowSuccess);
×
559
                return messageText;
×
560
            case WORKFLOW_FAILURE:
561
                version =  (DatasetVersion) targetObject;
×
562
                pattern = BundleUtil.getStringFromBundle("notification.email.workflow.failure");
×
563
                if (comment == null) {
×
564
                    comment = BundleUtil.getStringFromBundle("notification.email.workflow.nullMessage");
×
565
                }
566
                String[] paramArrayWorkflowFailure = {version.getDataset().getDisplayName(), getDatasetLink(version.getDataset()), comment};
×
567
                messageText += MessageFormat.format(pattern, paramArrayWorkflowFailure);
×
568
                return messageText;
×
569
            case STATUSUPDATED:
570
                version =  (DatasetVersion) targetObject;
×
571
                pattern = BundleUtil.getStringFromBundle("notification.email.status.change");
×
572
                String[] paramArrayStatus = {version.getDataset().getDisplayName(), (version.getExternalStatusLabel()==null) ? "<none>" : DatasetUtil.getLocaleExternalStatus(version.getExternalStatusLabel())};
×
573
                messageText += MessageFormat.format(pattern, paramArrayStatus);
×
574
                return messageText;
×
575
            case CREATEACC:
576
                String accountCreatedMessage = BundleUtil.getStringFromBundle("notification.email.welcome", Arrays.asList(
×
577
                        BrandingUtil.getInstallationBrandName(),
×
578
                        systemConfig.getGuidesBaseUrl(),
×
579
                        systemConfig.getGuidesVersion(),
×
580
                        BrandingUtil.getSupportTeamName(getSystemAddress().orElse(null)),
×
581
                        BrandingUtil.getSupportTeamEmailAddress(getSystemAddress().orElse(null))
×
582
                ));
583
                String optionalConfirmEmailAddon = confirmEmailService.optionalConfirmEmailAddonMsg(userNotification.getUser());
×
584
                accountCreatedMessage += optionalConfirmEmailAddon;
×
585
                logger.fine("accountCreatedMessage: " + accountCreatedMessage);
×
586
                return messageText += accountCreatedMessage;
×
587

588
            case CHECKSUMFAIL:
589
                dataset =  (Dataset) targetObject;
×
590
                String checksumFailMsg = BundleUtil.getStringFromBundle("notification.checksumfail", Arrays.asList(
×
591
                        dataset.getGlobalId().asString()
×
592
                ));
593
                logger.fine("checksumFailMsg: " + checksumFailMsg);
×
594
                return messageText += checksumFailMsg;
×
595

596
            case FILESYSTEMIMPORT:
597
                version =  (DatasetVersion) targetObject;
×
598
                String fileImportMsg = BundleUtil.getStringFromBundle("notification.mail.import.filesystem", Arrays.asList(
×
599
                        systemConfig.getDataverseSiteUrl(),
×
600
                        version.getDataset().getGlobalId().asString(),
×
601
                        version.getDataset().getDisplayName()
×
602
                ));
603
                logger.fine("fileImportMsg: " + fileImportMsg);
×
604
                return messageText += fileImportMsg;
×
605

606
            case GLOBUSUPLOADCOMPLETED:
607
                dataset =  (Dataset) targetObject;
×
608
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
609
                String uploadCompletedMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.completed", Arrays.asList(
×
610
                        systemConfig.getDataverseSiteUrl(),
×
611
                        dataset.getGlobalId().asString(),
×
612
                        dataset.getDisplayName(),
×
613
                        comment
614
                ))  ;
615
                return  uploadCompletedMessage;
×
616

617
            case GLOBUSDOWNLOADCOMPLETED:
618
                dataset =  (Dataset) targetObject;
×
619
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
620
                String downloadCompletedMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.download.completed", Arrays.asList(
×
621
                        systemConfig.getDataverseSiteUrl(),
×
622
                        dataset.getGlobalId().asString(),
×
623
                        dataset.getDisplayName(),
×
624
                        comment
625
                ))  ;
626
                return downloadCompletedMessage;
×
627
                        
628
            case GLOBUSUPLOADCOMPLETEDWITHERRORS:
629
                dataset =  (Dataset) targetObject;
×
630
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
631
                String uploadCompletedWithErrorsMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.completedWithErrors", Arrays.asList(
×
632
                        systemConfig.getDataverseSiteUrl(),
×
633
                        dataset.getGlobalId().asString(),
×
634
                        dataset.getDisplayName(),
×
635
                        comment
636
                ))  ;
637
                return  uploadCompletedWithErrorsMessage;
×
638
            
639
            case GLOBUSUPLOADREMOTEFAILURE:
NEW
640
                dataset =  (Dataset) targetObject;
×
NEW
641
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
NEW
642
                String uploadFailedRemotelyMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.failedRemotely", Arrays.asList(
×
NEW
643
                        systemConfig.getDataverseSiteUrl(),
×
NEW
644
                        dataset.getGlobalId().asString(),
×
NEW
645
                        dataset.getDisplayName(),
×
646
                        comment
647
                ))  ;
NEW
648
                return  uploadFailedRemotelyMessage;
×
649

650
            case GLOBUSUPLOADLOCALFAILURE:
NEW
651
                dataset =  (Dataset) targetObject;
×
NEW
652
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
NEW
653
                String uploadFailedLocallyMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.failedLocally", Arrays.asList(
×
NEW
654
                        systemConfig.getDataverseSiteUrl(),
×
NEW
655
                        dataset.getGlobalId().asString(),
×
NEW
656
                        dataset.getDisplayName(),
×
657
                        comment
658
                ))  ;
NEW
659
                return  uploadFailedLocallyMessage;
×
660
                
661
                case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
662
                dataset =  (Dataset) targetObject;
×
663
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
664
                String downloadCompletedWithErrorsMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.download.completedWithErrors", Arrays.asList(
×
665
                        systemConfig.getDataverseSiteUrl(),
×
666
                        dataset.getGlobalId().asString(),
×
667
                        dataset.getDisplayName(),
×
668
                        comment
669
                ))  ;
670
                return downloadCompletedWithErrorsMessage;
×
671

672
            case CHECKSUMIMPORT:
673
                version =  (DatasetVersion) targetObject;
×
674
                String checksumImportMsg = BundleUtil.getStringFromBundle("notification.import.checksum", Arrays.asList(
×
675
                        version.getDataset().getGlobalId().asString(),
×
676
                        version.getDataset().getDisplayName()
×
677
                ));
678
                logger.fine("checksumImportMsg: " + checksumImportMsg);
×
679
                return messageText += checksumImportMsg;
×
680

681
            case APIGENERATED:
682
                String message = BundleUtil.getStringFromBundle("notification.email.apiTokenGenerated", Arrays.asList(
×
683
                        userNotification.getUser().getFirstName(), userNotification.getUser().getFirstName() ));
×
684
                return message;
×
685

686
            case INGESTCOMPLETED:
687
                dataset = (Dataset) targetObject;
×
688
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
689
                String ingestedCompletedMessage = messageText + BundleUtil.getStringFromBundle("notification.ingest.completed", Arrays.asList(
×
690
                        systemConfig.getDataverseSiteUrl(),
×
691
                        dataset.getGlobalId().asString(),
×
692
                        dataset.getDisplayName(),
×
693
                        systemConfig.getGuidesBaseUrl(),
×
694
                        systemConfig.getGuidesVersion(),
×
695
                        comment
696
                ));
697

698
                return ingestedCompletedMessage;
×
699
            case INGESTCOMPLETEDWITHERRORS:
700
                dataset = (Dataset) targetObject;
×
701
                messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
702
                String ingestedCompletedWithErrorsMessage = messageText + BundleUtil.getStringFromBundle("notification.ingest.completedwitherrors", Arrays.asList(
×
703
                        systemConfig.getDataverseSiteUrl(),
×
704
                        dataset.getGlobalId().asString(),
×
705
                        dataset.getDisplayName(),
×
706
                        systemConfig.getGuidesBaseUrl(),
×
707
                        systemConfig.getGuidesVersion(),
×
708
                        comment
709
                ));
710

711
                return ingestedCompletedWithErrorsMessage;
×
712
            case DATASETMENTIONED:
713
                String additionalInfo = userNotification.getAdditionalInfo();
×
714
                dataset = (Dataset) targetObject;
×
715
                JsonObject citingResource = null;
×
716
                citingResource = JsonUtil.getJsonObject(additionalInfo);
×
717
                
718

719
                pattern = BundleUtil.getStringFromBundle("notification.email.datasetWasMentioned");
×
720
                Object[] paramArrayDatasetMentioned = {
×
721
                        userNotification.getUser().getName(),
×
722
                        BrandingUtil.getInstallationBrandName(), 
×
723
                        citingResource.getString("@type"),
×
724
                        citingResource.getString("@id"),
×
725
                        citingResource.getString("name"),
×
726
                        citingResource.getString("relationship"), 
×
727
                        systemConfig.getDataverseSiteUrl(),
×
728
                        dataset.getGlobalId().toString(), 
×
729
                        dataset.getDisplayName()};
×
730
                messageText = MessageFormat.format(pattern, paramArrayDatasetMentioned);
×
731
                return messageText;
×
732
            case REQUESTEDFILEACCESS:
733
                //Notification to requestor when they make a request
734
                datafile = (DataFile) targetObject;
×
735
                
736
                pattern = BundleUtil.getStringFromBundle("notification.email.requestedFileAccess");
×
737
                 messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
×
738
                 messageText += MessageFormat.format(pattern, getDvObjectLink(datafile), datafile.getOwner().getDisplayName());
×
739
                far = datafile.getAccessRequestForAssignee(requestor);
×
740
                gbr = far.getGuestbookResponse();
×
741
                if (gbr != null) {
×
742
                    messageText += MessageFormat.format(
×
743
                            BundleUtil.getStringFromBundle("notification.email.requestFileAccess.guestbookResponse"), gbr.toHtmlFormattedResponse());
×
744
                }
745
                return messageText;
×
746
        }
747

748
        return "";
×
749
    }
750

751
    public Object getObjectOfNotification (UserNotification userNotification){
752
        switch (userNotification.getType()) {
×
753
            case ASSIGNROLE:
754
            case REVOKEROLE:
755
                // Can either be a dataverse or dataset, so search both
756
                Dataverse dataverse = dataverseService.find(userNotification.getObjectId());
×
757
                if (dataverse != null) {
×
758
                    return dataverse;
×
759
                }
760

761
                Dataset dataset = datasetService.find(userNotification.getObjectId());
×
762
                return dataset;
×
763
            case CREATEDV:
764
                return dataverseService.find(userNotification.getObjectId());
×
765
            case REQUESTFILEACCESS:
766
            case REQUESTEDFILEACCESS:
767
                return dataFileService.find(userNotification.getObjectId());
×
768
            case GRANTFILEACCESS:
769
            case REJECTFILEACCESS:
770
            case DATASETCREATED:
771
            case DATASETMENTIONED:
772
                return datasetService.find(userNotification.getObjectId());
×
773
            case CREATEDS:
774
            case SUBMITTEDDS:
775
            case PUBLISHEDDS:
776
            case PUBLISHFAILED_PIDREG:
777
            case RETURNEDDS:
778
            case WORKFLOW_SUCCESS:
779
            case WORKFLOW_FAILURE:
780
            case STATUSUPDATED:
781
                return versionService.find(userNotification.getObjectId());
×
782
            case CREATEACC:
783
                return userNotification.getUser();
×
784
            case CHECKSUMFAIL:
785
                return datasetService.find(userNotification.getObjectId());
×
786
            case FILESYSTEMIMPORT:
787
                return versionService.find(userNotification.getObjectId());
×
788
            case GLOBUSUPLOADCOMPLETED:
789
            case GLOBUSUPLOADCOMPLETEDWITHERRORS:
790
            case GLOBUSUPLOADREMOTEFAILURE:
791
            case GLOBUSUPLOADLOCALFAILURE: 
792
            case GLOBUSDOWNLOADCOMPLETED:
793
            case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
794
                return datasetService.find(userNotification.getObjectId());
×
795
            case CHECKSUMIMPORT:
796
                return versionService.find(userNotification.getObjectId());
×
797
            case APIGENERATED:
798
                return userNotification.getUser();
×
799
            case INGESTCOMPLETED:
800
            case INGESTCOMPLETEDWITHERRORS:
801
                return datasetService.find(userNotification.getObjectId());
×
802

803
        }
804
        return null;
×
805
    }
806

807
    private String getUserEmailAddress(UserNotification notification) {
808
        if (notification != null) {
×
809
            if (notification.getUser() != null) {
×
810
                if (notification.getUser().getDisplayInfo() != null) {
×
811
                    if (notification.getUser().getDisplayInfo().getEmailAddress() != null) {
×
812
                        logger.fine("Email address: "+notification.getUser().getDisplayInfo().getEmailAddress());
×
813
                        return notification.getUser().getDisplayInfo().getEmailAddress();
×
814
                    }
815
                }
816
            }
817
        }
818

819
        logger.fine("no email address");
×
820
        return null; 
×
821
    }
822
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc