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

DataBiosphere / consent / #5929

19 May 2025 12:36PM UTC coverage: 78.551% (-0.2%) from 78.727%
#5929

push

web-flow
DT-1564, Progress Report DAC flow (#2523)

175 of 228 new or added lines in 17 files covered. (76.75%)

5 existing lines in 3 files now uncovered.

10027 of 12765 relevant lines covered (78.55%)

0.79 hits per line

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

60.53
/src/main/java/org/broadinstitute/consent/http/service/EmailService.java
1
package org.broadinstitute.consent.http.service;
2

3
import com.google.common.annotations.VisibleForTesting;
4
import com.google.inject.Inject;
5
import com.sendgrid.Response;
6
import com.sendgrid.helpers.mail.Mail;
7
import com.sendgrid.helpers.mail.objects.Content;
8
import com.sendgrid.helpers.mail.objects.Email;
9
import freemarker.template.Template;
10
import freemarker.template.TemplateException;
11
import java.io.IOException;
12
import java.io.StringWriter;
13
import java.io.Writer;
14
import java.time.Instant;
15
import java.util.Date;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Objects;
19
import javax.annotation.Nullable;
20
import org.broadinstitute.consent.http.configurations.ConsentConfiguration;
21
import org.broadinstitute.consent.http.db.MailMessageDAO;
22
import org.broadinstitute.consent.http.db.UserDAO;
23
import org.broadinstitute.consent.http.enumeration.EmailType;
24
import org.broadinstitute.consent.http.mail.SendGridAPI;
25
import org.broadinstitute.consent.http.mail.freemarker.FreeMarkerTemplateHelper;
26
import org.broadinstitute.consent.http.mail.message.DaaRequestMessage;
27
import org.broadinstitute.consent.http.mail.message.DarExpirationReminderMessage;
28
import org.broadinstitute.consent.http.mail.message.DarExpiredMessage;
29
import org.broadinstitute.consent.http.mail.message.DataCustodianApprovalMessage;
30
import org.broadinstitute.consent.http.mail.message.DatasetApprovedMessage;
31
import org.broadinstitute.consent.http.mail.message.DatasetDeniedMessage;
32
import org.broadinstitute.consent.http.mail.message.DatasetSubmittedMessage;
33
import org.broadinstitute.consent.http.mail.message.MailMessage;
34
import org.broadinstitute.consent.http.mail.message.NewCaseMessage;
35
import org.broadinstitute.consent.http.mail.message.NewDAAUploadResearcherMessage;
36
import org.broadinstitute.consent.http.mail.message.NewDAAUploadSOMessage;
37
import org.broadinstitute.consent.http.mail.message.NewDARRequestMessage;
38
import org.broadinstitute.consent.http.mail.message.NewProgressReportCaseMessage;
39
import org.broadinstitute.consent.http.mail.message.NewProgressReportRequestMessage;
40
import org.broadinstitute.consent.http.mail.message.NewResearcherLibraryRequestMessage;
41
import org.broadinstitute.consent.http.mail.message.ReminderMessage;
42
import org.broadinstitute.consent.http.mail.message.ResearcherDarApprovedMessage;
43
import org.broadinstitute.consent.http.mail.message.ResearcherApprovedProgressReportMessage;
44
import org.broadinstitute.consent.http.models.User;
45
import org.broadinstitute.consent.http.models.Vote;
46
import org.broadinstitute.consent.http.models.dto.DatasetMailDTO;
47
import org.broadinstitute.consent.http.util.ConsentLogger;
48

49
public class EmailService implements ConsentLogger {
50

51
  private final UserDAO userDAO;
52
  private final MailMessageDAO emailDAO;
53
  private final FreeMarkerTemplateHelper templateHelper;
54
  private final SendGridAPI sendGridAPI;
55
  private final String fromAccount;
56
  private final String serverUrl;
57

58
  @Inject
59
  public EmailService(
60
      UserDAO userDAO,
61
      MailMessageDAO emailDAO,
62
      SendGridAPI sendGridAPI,
63
      FreeMarkerTemplateHelper helper,
64
      ConsentConfiguration config) {
1✔
65
    this.userDAO = userDAO;
1✔
66
    this.templateHelper = helper;
1✔
67
    this.emailDAO = emailDAO;
1✔
68
    this.sendGridAPI = sendGridAPI;
1✔
69
    this.serverUrl = config.getServicesConfiguration().getLocalURL();
1✔
70
    this.fromAccount = config.getMailConfiguration().getGoogleAccount();
1✔
71
  }
1✔
72

73
  /**
74
   * This method saves an email (either sent or unsent) with all available metadata from the
75
   * SendGrid response.
76
   */
77
  private void saveEmailAndResponse(
78
      @Nullable Response response,
79
      @Nullable String entityReferenceId,
80
      @Nullable Integer voteId,
81
      Integer userId,
82
      EmailType emailType,
83
      String content) {
84
    Instant now = Instant.now();
1✔
85
    Instant dateSent = (Objects.nonNull(response) && response.getStatusCode() < 400) ? now : null;
1✔
86
    emailDAO.insert(
1✔
87
        entityReferenceId,
88
        voteId,
89
        userId,
90
        emailType.getTypeInt(),
1✔
91
        dateSent,
92
        content,
93
        Objects.nonNull(response) ? response.getBody() : null,
1✔
94
        Objects.nonNull(response) ? response.getStatusCode() : null,
1✔
95
        now);
96
  }
1✔
97

98
  @VisibleForTesting
99
  protected void sendMessage(MailMessage mailMessage, Integer userId)
100
      throws IOException, TemplateException {
101
    Writer out = new StringWriter();
1✔
102
    Template template = templateHelper.getTemplate(mailMessage.getTemplateName());
1✔
103
    template.process(mailMessage.createModel(serverUrl), out);
1✔
104
    String content = out.toString();
1✔
105
    Mail message = new Mail(new Email(fromAccount), mailMessage.createSubject(),
1✔
106
        new Email(mailMessage.toUser.getEmail()), new Content("text/html", content));
1✔
107
    Response response = sendGridAPI.sendMessage(message, mailMessage.toUser.getEmail());
1✔
108
    saveEmailAndResponse(
1✔
109
        response,
110
        mailMessage.getEntityReferenceId(),
1✔
111
        mailMessage.getVoteId(),
1✔
112
        userId,
113
        mailMessage.emailType,
114
        content);
115
  }
1✔
116

117
  public List<org.broadinstitute.consent.http.models.mail.MailMessage> fetchEmailMessagesByType(
118
      EmailType emailType, Integer limit,
119
      Integer offset) {
120
    return emailDAO.fetchMessagesByType(emailType.getTypeInt(), limit, offset);
1✔
121
  }
122

123
  public List<org.broadinstitute.consent.http.models.mail.MailMessage> fetchEmailMessagesByCreateDate(
124
      Date start, Date end, Integer limit,
125
      Integer offset) {
126
    return emailDAO.fetchMessagesByCreateDate(start, end, limit, offset);
1✔
127
  }
128

129

130
  public void sendResearcherDarApproved(
131
      String darCode,
132
      Integer researcherId,
133
      List<DatasetMailDTO> datasets,
134
      String dataUseRestriction)
135
      throws TemplateException, IOException {
NEW
136
    User user = userDAO.findUserById(researcherId);
×
NEW
137
    sendMessage(
×
138
        new ResearcherDarApprovedMessage(user, darCode, datasets, dataUseRestriction), researcherId);
UNCOV
139
  }
×
140

141
  public void sendResearcherProgressReportApproved(
142
      String darCode,
143
      Integer researcherId,
144
      List<DatasetMailDTO> datasets,
145
      String dataUseRestriction)
146
      throws TemplateException, IOException {
147
    User user = userDAO.findUserById(researcherId);
×
148
    sendMessage(
×
149
        new ResearcherApprovedProgressReportMessage(user, darCode, datasets, dataUseRestriction), researcherId);
150
  }
×
151

152
  public void sendDataCustodianApprovalMessage(
153
      User custodian,
154
      String darCode,
155
      List<DatasetMailDTO> datasets,
156
      String dataDepositorName,
157
      String researcherEmail)
158
      throws TemplateException, IOException {
159
    sendMessage(
×
160
        new DataCustodianApprovalMessage(
161
            custodian, darCode, datasets, dataDepositorName, researcherEmail),
162
        custodian.getUserId());
×
163
  }
×
164

165
  public void sendDatasetSubmittedMessage(
166
      User dacChair, User dataSubmitter, String dacName, String datasetName)
167
      throws TemplateException, IOException {
168
    sendMessage(
1✔
169
        new DatasetSubmittedMessage(dacChair, dataSubmitter.getDisplayName(), datasetName, dacName),
1✔
170
        dacChair.getUserId());
1✔
171
  }
1✔
172

173
  public void sendDatasetApprovedMessage(User user, String dacName, String datasetName)
174
      throws TemplateException, IOException {
175
    sendMessage(new DatasetApprovedMessage(user, dacName, datasetName), user.getUserId());
×
176
  }
×
177

178
  public void sendDatasetDeniedMessage(
179
      User user, String dacName, String datasetName, String dacEmail)
180
      throws TemplateException, IOException {
181
    sendMessage(new DatasetDeniedMessage(user, dacName, datasetName, dacEmail), user.getUserId());
×
182
  }
×
183

184
  public void sendNewResearcherMessage(User researcher, User signingOfficial)
185
      throws TemplateException, IOException {
186
    sendMessage(
1✔
187
        new NewResearcherLibraryRequestMessage(signingOfficial, researcher),
188
        researcher.getUserId());
1✔
189
  }
1✔
190

191
  public void sendDaaRequestMessage(
192
      User signingOfficial, User requestUser, String daaName, Integer daaId)
193
      throws TemplateException, IOException {
194
    sendMessage(
1✔
195
        new DaaRequestMessage(signingOfficial, requestUser, daaName, daaId),
196
        requestUser.getUserId());
1✔
197
  }
1✔
198

199
  public void sendNewDAAUploadSOMessage(
200
      User signingOfficial,
201
      String dacName,
202
      String previousDaaName,
203
      String newDaaName,
204
      Integer userId)
205
      throws TemplateException, IOException {
206
    sendMessage(
1✔
207
        new NewDAAUploadSOMessage(signingOfficial, dacName, previousDaaName, newDaaName), userId);
208
  }
1✔
209

210
  public void sendNewDAAUploadResearcherMessage(
211
      User researcher, String dacName, String previousDaaName, String newDaaName, Integer userId)
212
      throws TemplateException, IOException {
213
    sendMessage(
1✔
214
        new NewDAAUploadResearcherMessage(
215
            researcher, dacName, previousDaaName, newDaaName),
216
        userId);
217
  }
1✔
218

219
  public void sendDarNewCollectionElectionMessage(List<User> users, String darCode)
220
      throws IOException, TemplateException {
NEW
221
    String electionType = "Data Access Request";
×
NEW
222
    for (User user : users) {
×
NEW
223
      sendMessage(new NewCaseMessage(user, darCode, electionType), user.getUserId());
×
UNCOV
224
    }
×
NEW
225
  }
×
226

227
  public void sendProgressReportNewCollectionElectionMessage(List<User> users, String darCode)
228
      throws IOException, TemplateException {
NEW
229
    for (User user : users) {
×
NEW
230
      sendMessage(new NewProgressReportCaseMessage(user, darCode), user.getUserId());
×
NEW
231
    }
×
NEW
232
  }
×
233

234
  public void sendNewDARRequestEmail(
235
      User user, Map<String, List<String>> sendList, String researcherName, String darCode)
236
      throws TemplateException, IOException {
NEW
237
        sendMessage(new NewDARRequestMessage(user, darCode, sendList, researcherName),
×
NEW
238
        user.getUserId());
×
NEW
239
  }
×
240

241
  public void sendNewProgressReportRequestEmail(
242
      User user, Map<String, List<String>> sendList, String researcherName, String darCode, String referenceId)
243
      throws TemplateException, IOException {
NEW
244
      sendMessage(new NewProgressReportRequestMessage(user, darCode, referenceId, sendList, researcherName),
×
NEW
245
        user.getUserId());
×
UNCOV
246
  }
×
247

248
  /**
249
   * Send a message to a researcher that their data access request has expired.
250
   *
251
   * @param researcher  the researcher to send the message to
252
   * @param darCode     the data access request code that's expired
253
   * @param userId      the user id of the person sending the message
254
   * @param referenceId the data access request reference id that's expired
255
   */
256
  public void sendDarExpiredMessage(User researcher, String darCode, Integer userId,
257
      String referenceId)
258
      throws TemplateException, IOException {
259
    sendMessage(new DarExpiredMessage(researcher, darCode, referenceId), userId);
1✔
260
  }
1✔
261

262
  /**
263
   * Remind the user that their data access request is about to expire.
264
   *
265
   * @param user        the user to send the message to
266
   * @param darCode     the data access request code that's about to expire
267
   * @param userId      the user id of the person sending the message
268
   * @param referenceId the data access request reference id that is expiring
269
   */
270
  public void sendDarExpirationReminderMessage(User user, String darCode, Integer userId,
271
      String referenceId)
272
      throws TemplateException, IOException {
273
    sendMessage(new DarExpirationReminderMessage(user, darCode, referenceId), userId);
1✔
274
  }
1✔
275

276
  public void sendReminderMessage(User user, Vote vote, String darCode, String electionType, String url)
277
      throws TemplateException, IOException {
NEW
278
    sendMessage(new ReminderMessage(user, vote, darCode, electionType, url), user.getUserId());
×
NEW
279
  }
×
280

281
}
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

© 2026 Coveralls, Inc