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

DataBiosphere / consent / #6333

15 Aug 2025 12:17PM UTC coverage: 83.37% (+0.03%) from 83.338%
#6333

push

web-flow
DT-2091: Update DAC Approve Dataset performance (#2636)

Co-authored-by: otchet-broad <111771148+otchet-broad@users.noreply.github.com>

83 of 105 new or added lines in 5 files covered. (79.05%)

4 existing lines in 1 file now uncovered.

10949 of 13133 relevant lines covered (83.37%)

0.83 hits per line

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

77.19
/src/main/java/org/broadinstitute/consent/http/db/SamDAO.java
1
package org.broadinstitute.consent.http.db;
2

3
import com.google.api.client.http.EmptyContent;
4
import com.google.api.client.http.GenericUrl;
5
import com.google.api.client.http.HttpRequest;
6
import com.google.api.client.http.HttpResponse;
7
import com.google.common.util.concurrent.FutureCallback;
8
import com.google.common.util.concurrent.Futures;
9
import com.google.common.util.concurrent.ListenableFuture;
10
import com.google.common.util.concurrent.ListeningExecutorService;
11
import com.google.common.util.concurrent.MoreExecutors;
12
import com.google.gson.Gson;
13
import com.google.gson.JsonElement;
14
import com.google.gson.JsonParser;
15
import com.google.gson.JsonSyntaxException;
16
import com.google.gson.reflect.TypeToken;
17
import jakarta.ws.rs.ServerErrorException;
18
import jakarta.ws.rs.WebApplicationException;
19
import jakarta.ws.rs.core.MediaType;
20
import java.lang.reflect.Type;
21
import java.util.ArrayList;
22
import java.util.List;
23
import java.util.concurrent.ExecutorService;
24
import org.broadinstitute.consent.http.configurations.ServicesConfiguration;
25
import org.broadinstitute.consent.http.models.AuthUser;
26
import org.broadinstitute.consent.http.models.sam.EmailResponse;
27
import org.broadinstitute.consent.http.models.sam.ResourceType;
28
import org.broadinstitute.consent.http.models.sam.TosResponse;
29
import org.broadinstitute.consent.http.models.sam.UserStatus;
30
import org.broadinstitute.consent.http.models.sam.UserStatusDiagnostics;
31
import org.broadinstitute.consent.http.models.sam.UserStatusInfo;
32
import org.broadinstitute.consent.http.util.ConsentLogger;
33
import org.broadinstitute.consent.http.util.HttpClientUtil;
34
import org.broadinstitute.consent.http.util.ThreadUtils;
35
import org.checkerframework.checker.nullness.qual.NonNull;
36
import org.checkerframework.checker.nullness.qual.Nullable;
37

38
public class SamDAO implements ConsentLogger {
39

40
  private final ExecutorService executorService = new ThreadUtils().getExecutorService(
1✔
41
      SamDAO.class);
42
  private final HttpClientUtil clientUtil;
43
  private final ServicesConfiguration configuration;
44
  private final Integer connectTimeoutMilliseconds;
45
  public final Integer readTimeoutMilliseconds;
46

47
  public SamDAO(HttpClientUtil clientUtil, ServicesConfiguration configuration) {
1✔
48
    this.clientUtil = clientUtil;
1✔
49
    this.configuration = configuration;
1✔
50
    // Defaults to 10 seconds
51
    this.connectTimeoutMilliseconds = configuration.getTimeoutSeconds() * 1000;
1✔
52
    // Defaults to 60 seconds
53
    this.readTimeoutMilliseconds = configuration.getTimeoutSeconds() * 6000;
1✔
54
  }
1✔
55

56
  public List<ResourceType> getResourceTypes(AuthUser authUser) throws Exception {
57
    GenericUrl genericUrl = new GenericUrl(configuration.getV1ResourceTypesUrl());
1✔
58
    HttpRequest request = clientUtil.buildGetRequest(genericUrl, authUser);
1✔
59
    HttpResponse response = executeRequest(request);
1✔
60
    if (!response.isSuccessStatusCode()) {
1✔
61
      logException("Error getting resource types from Sam: " + response.getStatusMessage(),
×
62
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
63
    }
64
    String body = response.parseAsString();
1✔
65
    Type resourceTypesListType = new TypeToken<ArrayList<ResourceType>>() {
1✔
66
    }.getType();
1✔
67
    return new Gson().fromJson(body, resourceTypesListType);
1✔
68
  }
69

70
  public UserStatusInfo getRegistrationInfo(AuthUser authUser) throws Exception {
71
    GenericUrl genericUrl = new GenericUrl(configuration.getRegisterUserV2SelfInfoUrl());
1✔
72
    HttpRequest request = clientUtil.buildGetRequest(genericUrl, authUser);
1✔
73
    HttpResponse response = executeRequest(request);
1✔
74
    if (!response.isSuccessStatusCode()) {
1✔
75
      logException(
×
76
          "Error getting user registration information from Sam: " + response.getStatusMessage(),
×
77
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
78
    }
79
    String body = response.parseAsString();
1✔
80
    return new Gson().fromJson(body, UserStatusInfo.class);
1✔
81
  }
82

83
  public UserStatusDiagnostics getSelfDiagnostics(AuthUser authUser) throws Exception {
84
    GenericUrl genericUrl = new GenericUrl(configuration.getV2SelfDiagnosticsUrl());
1✔
85
    HttpRequest request = clientUtil.buildGetRequest(genericUrl, authUser);
1✔
86
    HttpResponse response = executeRequest(request);
1✔
87
    if (!response.isSuccessStatusCode()) {
1✔
88
      logException(
×
89
          "Error getting enabled statuses of user from Sam: " + response.getStatusMessage(),
×
90
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
91
    }
92
    String body = response.parseAsString();
1✔
93
    return new Gson().fromJson(body, UserStatusDiagnostics.class);
1✔
94
  }
95

96
  public UserStatus postRegistrationInfo(AuthUser authUser) throws Exception {
97
    GenericUrl genericUrl = new GenericUrl(configuration.postRegisterUserV2SelfUrl());
1✔
98
    HttpRequest request = clientUtil.buildPostRequest(genericUrl, new EmptyContent(), authUser);
1✔
99
    HttpResponse response = executeRequest(request);
1✔
100
    String body = response.parseAsString();
1✔
101
    if (!response.isSuccessStatusCode()) {
1✔
102
      var errorMsg = getErrorMessage(authUser, body);
1✔
103
      Exception e = new WebApplicationException(errorMsg, response.getStatusCode());
1✔
104
      logException(errorMsg, new Exception(body));
1✔
105
      throw e;
1✔
106
    }
107
    return new Gson().fromJson(body, UserStatus.class);
1✔
108
  }
109

110
  public static String getErrorMessage(AuthUser authUser, String body) {
111
    var errorMsg = String.format("Error posting user registration information. Email: %s.",
1✔
112
        authUser.getEmail());
1✔
113
    if (body == null || body.isEmpty()) {
1✔
114
      return errorMsg;
1✔
115
    }
116
    try {
117
      JsonElement messageElement = JsonParser.parseString(body).getAsJsonObject().get("message");
1✔
118
      String message = messageElement != null ? messageElement.getAsString() : body;
1✔
119
      if (message.contains("Cannot update azureB2cId")) {
1✔
120
        return String.format(
1✔
121
            "Email: %s. You may have previously signed in with a different authentication provider (Google or Microsoft). Please sign in with that provider. For more information visit: https://support.terra.bio/hc/en-us/community/posts/24089648317467-Cannot-update-azureB2cId-for-user",
122
            authUser.getEmail());
1✔
123
      }
124
      return String.format(errorMsg + " %s.", message);
1✔
125
    } catch (JsonSyntaxException e) {  // If the body is not a valid JSON
1✔
126
      return String.format(errorMsg + " %s.", body);
1✔
127
    }
128
  }
129

130
  public void asyncPostRegistrationInfo(AuthUser authUser) {
131
    ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(
1✔
132
        executorService);
133
    ListenableFuture<UserStatus> userStatusFuture =
1✔
134
        listeningExecutorService.submit(() -> postRegistrationInfo(authUser));
1✔
135
    Futures.addCallback(
1✔
136
        userStatusFuture,
137
        new FutureCallback<>() {
1✔
138
          @Override
139
          public void onSuccess(@Nullable UserStatus userStatus) {
140
            logInfo("Successfully registered user in Sam: " + authUser.getEmail());
1✔
141
          }
1✔
142

143
          @Override
144
          public void onFailure(@NonNull Throwable throwable) {
NEW
145
            logWarn("Async Post Registration Failure for user: " + authUser.getEmail() + "; "
×
NEW
146
                + throwable.getMessage());
×
UNCOV
147
          }
×
148
        },
149
        listeningExecutorService);
150
  }
1✔
151

152
  public String getToSText() throws Exception {
153
    GenericUrl genericUrl = new GenericUrl(configuration.getToSTextUrl());
1✔
154
    HttpRequest request = clientUtil.buildUnAuthedGetRequest(genericUrl);
1✔
155
    request.getHeaders().setAccept(MediaType.TEXT_PLAIN);
1✔
156
    HttpResponse response = executeRequest(request);
1✔
157
    if (!response.isSuccessStatusCode()) {
1✔
158
      logException("Error getting Terms of Service text from Sam: " + response.getStatusMessage(),
×
159
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
160
    }
161
    return response.parseAsString();
1✔
162
  }
163

164
  public TosResponse getTosResponse(AuthUser authUser) throws Exception {
165
    GenericUrl genericUrl = new GenericUrl(configuration.getSelfTosUrl());
1✔
166
    HttpRequest request = clientUtil.buildGetRequest(genericUrl, authUser);
1✔
167
    HttpResponse response = executeRequest(request);
1✔
168
    if (!response.isSuccessStatusCode()) {
1✔
NEW
169
      logException(String.format("Error getting Terms of Service: %s for user %s",
×
NEW
170
              response.getStatusMessage(), authUser.getEmail()),
×
UNCOV
171
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
172
    }
173
    String body = response.parseAsString();
1✔
174
    return new Gson().fromJson(body, TosResponse.class);
1✔
175
  }
176

177
  public int acceptTosStatus(AuthUser authUser) throws Exception {
178
    GenericUrl genericUrl = new GenericUrl(configuration.acceptTosUrl());
1✔
179
    HttpRequest request = clientUtil.buildPutRequest(genericUrl, new EmptyContent(), authUser);
1✔
180
    HttpResponse response = executeRequest(request);
1✔
181
    if (!response.isSuccessStatusCode()) {
1✔
NEW
182
      logException(String.format("Error accepting Terms of Service: %s for user %s",
×
NEW
183
              response.getStatusMessage(), authUser.getEmail()),
×
UNCOV
184
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
185
    }
186
    return response.getStatusCode();
1✔
187
  }
188

189
  public int rejectTosStatus(AuthUser authUser) throws Exception {
190
    GenericUrl genericUrl = new GenericUrl(configuration.rejectTosUrl());
1✔
191
    HttpRequest request = clientUtil.buildPutRequest(genericUrl, new EmptyContent(), authUser);
1✔
192
    HttpResponse response = executeRequest(request);
1✔
193
    if (!response.isSuccessStatusCode()) {
1✔
194
      logException(
×
NEW
195
          String.format("Error removing Terms of Service: %s for user %s",
×
NEW
196
              response.getStatusMessage(), authUser.getEmail()),
×
UNCOV
197
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
198
    }
199
    return response.getStatusCode();
1✔
200
  }
201

202
  public EmailResponse getV1UserByEmail(AuthUser authUser, String email) throws Exception {
203
    GenericUrl genericUrl = new GenericUrl(configuration.getV1UserUrl(email));
1✔
204
    HttpRequest request = clientUtil.buildGetRequest(genericUrl, authUser);
1✔
205
    HttpResponse response = executeRequest(request);
1✔
206
    if (!response.isSuccessStatusCode()) {
1✔
207
      logException(
×
208
          "Error getting user by email from Sam: " + response.getStatusMessage(),
×
209
          new ServerErrorException(response.getStatusMessage(), response.getStatusCode()));
×
210
    }
211
    String body = response.parseAsString();
1✔
212
    return new Gson().fromJson(body, EmailResponse.class);
1✔
213
  }
214

215
  /**
216
   * Private method to handle the general case of sending requests to Sam. We inject timeouts here
217
   * to prevent Sam from impacting API performance. The default is 10 seconds which should be more
218
   * than enough for Sam calls.
219
   *
220
   * @param request The HttpRequest
221
   * @return The HttpResponse
222
   */
223
  private HttpResponse executeRequest(HttpRequest request) {
224
    request.setConnectTimeout(connectTimeoutMilliseconds);
1✔
225
    request.setReadTimeout(readTimeoutMilliseconds);
1✔
226
    return clientUtil.handleHttpRequest(request);
1✔
227
  }
228

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