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

DataBiosphere / consent / #5880

12 May 2025 01:41PM UTC coverage: 78.691% (-0.07%) from 78.764%
#5880

push

web-flow
[DT-400-maven]: Bump the maven-dependencies group with 2 updates (#2525)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

10063 of 12788 relevant lines covered (78.69%)

0.79 hits per line

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

89.8
/src/main/java/org/broadinstitute/consent/http/service/UserService.java
1
package org.broadinstitute.consent.http.service;
2

3
import static org.broadinstitute.consent.http.enumeration.UserFields.ERA_EXPIRATION_DATE;
4
import static org.broadinstitute.consent.http.enumeration.UserFields.ERA_STATUS;
5

6
import com.google.gson.Gson;
7
import com.google.gson.JsonArray;
8
import com.google.gson.JsonElement;
9
import com.google.gson.JsonObject;
10
import com.google.inject.Inject;
11
import jakarta.ws.rs.BadRequestException;
12
import jakarta.ws.rs.NotFoundException;
13
import java.time.Instant;
14
import java.util.Collections;
15
import java.util.Date;
16
import java.util.List;
17
import java.util.Objects;
18
import java.util.stream.Collectors;
19
import java.util.stream.Stream;
20
import org.apache.commons.collections4.CollectionUtils;
21
import org.apache.commons.lang3.StringUtils;
22
import org.broadinstitute.consent.http.db.AcknowledgementDAO;
23
import org.broadinstitute.consent.http.db.DaaDAO;
24
import org.broadinstitute.consent.http.db.FileStorageObjectDAO;
25
import org.broadinstitute.consent.http.db.InstitutionDAO;
26
import org.broadinstitute.consent.http.db.LibraryCardDAO;
27
import org.broadinstitute.consent.http.db.SamDAO;
28
import org.broadinstitute.consent.http.db.UserDAO;
29
import org.broadinstitute.consent.http.db.UserPropertyDAO;
30
import org.broadinstitute.consent.http.db.UserRoleDAO;
31
import org.broadinstitute.consent.http.db.VoteDAO;
32
import org.broadinstitute.consent.http.enumeration.UserFields;
33
import org.broadinstitute.consent.http.enumeration.UserRoles;
34
import org.broadinstitute.consent.http.exceptions.ConsentConflictException;
35
import org.broadinstitute.consent.http.exceptions.LibraryCardRequiredException;
36
import org.broadinstitute.consent.http.models.AuthUser;
37
import org.broadinstitute.consent.http.models.DataAccessAgreement;
38
import org.broadinstitute.consent.http.models.Institution;
39
import org.broadinstitute.consent.http.models.LibraryCard;
40
import org.broadinstitute.consent.http.models.User;
41
import org.broadinstitute.consent.http.models.UserProperty;
42
import org.broadinstitute.consent.http.models.UserRole;
43
import org.broadinstitute.consent.http.models.UserUpdateFields;
44
import org.broadinstitute.consent.http.models.Vote;
45
import org.broadinstitute.consent.http.resources.Resource;
46
import org.broadinstitute.consent.http.service.dao.DraftServiceDAO;
47
import org.broadinstitute.consent.http.service.dao.UserServiceDAO;
48
import org.broadinstitute.consent.http.util.ConsentLogger;
49
import org.broadinstitute.consent.http.util.gson.GsonUtil;
50

51
public class UserService implements ConsentLogger {
52

53
  public static final String LIBRARY_CARDS_FIELD = "libraryCards";
54
  public static final String USER_PROPERTIES_FIELD = "properties";
55
  public static final String USER_STATUS_INFO_FIELD = "userStatusInfo";
56

57
  private final UserPropertyDAO userPropertyDAO;
58
  private final UserDAO userDAO;
59
  private final UserRoleDAO userRoleDAO;
60
  private final VoteDAO voteDAO;
61
  private final InstitutionDAO institutionDAO;
62
  private final LibraryCardDAO libraryCardDAO;
63
  private final AcknowledgementDAO acknowledgementDAO;
64
  private final FileStorageObjectDAO fileStorageObjectDAO;
65
  private final SamDAO samDAO;
66
  private final UserServiceDAO userServiceDAO;
67
  private final DaaDAO daaDAO;
68
  private final DraftServiceDAO draftServiceDAO;
69
  private final InstitutionService institutionService;
70

71
  @Inject
72
  public UserService(UserDAO userDAO, UserPropertyDAO userPropertyDAO, UserRoleDAO userRoleDAO,
73
      VoteDAO voteDAO, InstitutionDAO institutionDAO, LibraryCardDAO libraryCardDAO,
74
      AcknowledgementDAO acknowledgementDAO, FileStorageObjectDAO fileStorageObjectDAO,
75
      SamDAO samDAO, UserServiceDAO userServiceDAO, DaaDAO daaDAO, DraftServiceDAO draftServiceDAO,
76
      InstitutionService institutionService) {
1✔
77
    this.userDAO = userDAO;
1✔
78
    this.userPropertyDAO = userPropertyDAO;
1✔
79
    this.userRoleDAO = userRoleDAO;
1✔
80
    this.voteDAO = voteDAO;
1✔
81
    this.institutionDAO = institutionDAO;
1✔
82
    this.libraryCardDAO = libraryCardDAO;
1✔
83
    this.acknowledgementDAO = acknowledgementDAO;
1✔
84
    this.fileStorageObjectDAO = fileStorageObjectDAO;
1✔
85
    this.samDAO = samDAO;
1✔
86
    this.userServiceDAO = userServiceDAO;
1✔
87
    this.daaDAO = daaDAO;
1✔
88
    this.draftServiceDAO = draftServiceDAO;
1✔
89
    this.institutionService = institutionService;
1✔
90
  }
1✔
91

92
  /**
93
   * Update a select group of user fields for a user id.
94
   *
95
   * @param userUpdateFields A UserUpdateFields object for all update information
96
   * @param userId           The User's ID
97
   * @return The updated User
98
   */
99
  public User updateUserFieldsById(UserUpdateFields userUpdateFields, Integer userId) {
100
    if (Objects.nonNull(userUpdateFields)) {
1✔
101
      // Update Primary User Fields
102
      if (Objects.nonNull(userUpdateFields.getDisplayName())) {
1✔
103
        userDAO.updateDisplayName(userId, userUpdateFields.getDisplayName());
1✔
104
      }
105
      if (Objects.nonNull(userUpdateFields.getInstitutionId())) {
1✔
106
        userDAO.updateInstitutionId(userId, userUpdateFields.getInstitutionId());
1✔
107
      }
108
      if (Objects.nonNull(userUpdateFields.getEmailPreference())) {
1✔
109
        userDAO.updateEmailPreference(userId, userUpdateFields.getEmailPreference());
1✔
110
      }
111
      if (Objects.nonNull(userUpdateFields.getEraCommonsId())) {
1✔
112
        userDAO.updateEraCommonsId(userId, userUpdateFields.getEraCommonsId());
1✔
113
      }
114

115
      // Update User Properties
116
      List<UserProperty> userProps = userUpdateFields.buildUserProperties(userId);
1✔
117
      if (!userProps.isEmpty()) {
1✔
118
        userPropertyDAO.deletePropertiesByUserAndKey(userProps);
1✔
119
        userPropertyDAO.insertAll(userProps);
1✔
120
      }
121

122
      // Handle Roles
123
      if (Objects.nonNull(userUpdateFields.getUserRoleIds())) {
1✔
124
        List<Integer> currentRoleIds = userRoleDAO.findRolesByUserId(userId).stream()
1✔
125
            .map(UserRole::getRoleId).collect(Collectors.toList());
1✔
126
        List<Integer> roleIdsToAdd = userUpdateFields.getRoleIdsToAdd(currentRoleIds);
1✔
127
        List<Integer> roleIdsToRemove = userUpdateFields.getRoleIdsToRemove(currentRoleIds);
1✔
128
        // Add the new role ids to the user
129
        if (!roleIdsToAdd.isEmpty()) {
1✔
130
          List<UserRole> newRoles = roleIdsToAdd.stream()
1✔
131
              .map(id -> new UserRole(id,
1✔
132
                  Objects.requireNonNull(UserRoles.getUserRoleFromId(id)).getRoleName()))
1✔
133
              .collect(Collectors.toList());
1✔
134
          userRoleDAO.insertUserRoles(newRoles, userId);
1✔
135
        }
136
        // Remove the old role ids from the user
137
        if (!roleIdsToRemove.isEmpty()) {
1✔
138
          userRoleDAO.removeUserRoles(userId, roleIdsToRemove);
1✔
139
        }
140
      }
141

142
    }
143
    return findUserById(userId);
1✔
144
  }
145

146
  public void insertRoleAndInstitutionForUser(UserRole role, User user) {
147
    var userId = user.getUserId();
1✔
148
    try {
149
      if (user.getInstitutionId() == null) {
1✔
150
        Institution institution = institutionService.findInstitutionForEmail(user.getEmail());
1✔
151
        if (institution == null) {
1✔
152
          throw new BadRequestException(
1✔
153
              "No institution found for user: %s".formatted(user.getEmail()));
1✔
154
        }
155
        userServiceDAO.insertRoleAndInstitutionTxn(role, institution.getId(), userId);
1✔
156
      } else {
1✔
157
        userRoleDAO.insertSingleUserRole(role.getRoleId(), userId);
1✔
158
      }
159
    } catch (Exception e) {
1✔
160
      logException(
1✔
161
          "Error when updating user: %s, role: %s".formatted(userId, role), e);
1✔
162
      throw e;
1✔
163
    }
1✔
164
  }
1✔
165

166
  public User createUser(User user) {
167
    // Default role is researcher.
168
    if (CollectionUtils.isEmpty(user.getRoles())) {
1✔
169
      user.setResearcherRole();
1✔
170
    }
171
    validateRequiredFields(user);
1✔
172
    User existingUser = userDAO.findUserByEmail(user.getEmail());
1✔
173
    if (Objects.nonNull(existingUser)) {
1✔
174
      throw new BadRequestException("User exists with this email address: " + user.getEmail());
1✔
175
    }
176
    Institution institution = institutionService.findInstitutionForEmail(user.getEmail());
1✔
177
    if (institution != null) {
1✔
178
      user.setInstitutionId(institution.getId());
1✔
179
    }
180
    Integer userId = userDAO.insertUser(user.getEmail(), user.getDisplayName(),
1✔
181
        user.getInstitutionId(), new Date());
1✔
182
    insertUserRoles(user.getRoles(), userId);
1✔
183
    addExistingLibraryCards(user);
1✔
184
    return userDAO.findUserById(userId);
1✔
185
  }
186

187
  public User findUserById(Integer id) throws NotFoundException {
188
    User user = userDAO.findUserById(id);
1✔
189
    if (user == null) {
1✔
190
      throw new NotFoundException("Unable to find user with id: " + id);
1✔
191
    }
192
    List<LibraryCard> cards = libraryCardDAO.findLibraryCardsByUserId(user.getUserId());
1✔
193
    if (Objects.nonNull(cards) && !cards.isEmpty()) {
1✔
194
      user.setLibraryCards(cards);
1✔
195
    }
196
    return user;
1✔
197
  }
198

199
  public User findUserByEmail(String email) throws NotFoundException {
200
    User user = userDAO.findUserByEmail(email);
1✔
201
    if (user == null) {
1✔
202
      throw new NotFoundException("Unable to find user with email: " + email);
1✔
203
    }
204
    List<LibraryCard> cards = libraryCardDAO.findLibraryCardsByUserId(user.getUserId());
1✔
205
    if (Objects.nonNull(cards) && !cards.isEmpty()) {
1✔
206
      user.setLibraryCards(cards);
×
207
    }
208
    return user;
1✔
209
  }
210

211
  /**
212
   * Find users as a specific role, e.g., Admins can see all users, other roles can only see a
213
   * subset of users.
214
   *
215
   * @param user     The user making the request
216
   * @param roleName The role the user is making the request as
217
   * @return List of Users for specified role name
218
   */
219
  public List<User> getUsersAsRole(User user, String roleName) {
220
    switch (roleName) {
1✔
221
      // SigningOfficial console is technically pulling LCs, it's just bringing associated users along for the ride
222
      // However LCs can be created for users not yet registered in the system
223
      // As such a more specialized query is needed to produce the proper listing
224
      case Resource.SIGNINGOFFICIAL:
225
        Integer institutionId = user.getInstitutionId();
1✔
226
        if (Objects.nonNull(user.getInstitutionId())) {
1✔
227
          return userDAO.getUsersFromInstitutionWithCards(institutionId);
1✔
228
        } else {
229
          throw new NotFoundException("Signing Official (user: " + user.getDisplayName()
1✔
230
              + ") is not associated with an Institution.");
231
        }
232
      case Resource.ADMIN:
233
        return userDAO.findUsersWithLCsAndInstitution();
1✔
234
      default:
235
        // do nothing
236
    }
237
    return Collections.emptyList();
×
238
  }
239

240
  public List<SimplifiedUser> getUsersByDaaId(Integer daaId) {
241
    if (Objects.isNull(daaId)) {
1✔
242
      throw new IllegalArgumentException();
×
243
    }
244
    DataAccessAgreement daa = daaDAO.findById(daaId);
1✔
245
    if (Objects.isNull(daa)) {
1✔
246
      throw new NotFoundException();
1✔
247
    }
248
    List<User> users = userDAO.getUsersWithCardsByDaaId(daaId);
1✔
249
    return users.stream().map(SimplifiedUser::new).collect(Collectors.toList());
1✔
250
  }
251

252
  public void deleteUserByEmail(String email) {
253
    User user = userDAO.findUserByEmail(email);
1✔
254
    if (user == null) {
1✔
255
      throw new NotFoundException("The user for the specified E-Mail address does not exist");
×
256
    }
257
    Integer userId = user.getUserId();
1✔
258
    List<Integer> roleIds = userRoleDAO.
1✔
259
        findRolesByUserId(userId).
1✔
260
        stream().
1✔
261
        map(UserRole::getRoleId).
1✔
262
        collect(Collectors.toList());
1✔
263
    if (!roleIds.isEmpty()) {
1✔
264
      userRoleDAO.removeUserRoles(userId, roleIds);
×
265
    }
266
    List<Vote> votes = voteDAO.findVotesByUserId(userId);
1✔
267
    if (!votes.isEmpty()) {
1✔
268
      List<Integer> voteIds = votes.stream().map(Vote::getVoteId).collect(Collectors.toList());
×
269
      voteDAO.removeVotesByIds(voteIds);
×
270
    }
271
    try {
272
      draftServiceDAO.deleteDraftsByUser(user);
1✔
273
    } catch (Exception e) {
×
274
      logException(
×
275
          String.format("Unable to delete all drafts and files for userId %d. Error was: %s",
×
276
              userId, e.getMessage()), e);
×
277
    }
1✔
278
    institutionDAO.deleteAllInstitutionsByUser(userId);
1✔
279
    userPropertyDAO.deleteAllPropertiesByUser(userId);
1✔
280
    libraryCardDAO.deleteAllLibraryCardsByUser(userId);
1✔
281
    acknowledgementDAO.deleteAllAcknowledgementsByUser(userId);
1✔
282
    fileStorageObjectDAO.deleteAllUserFiles(userId);
1✔
283
    userDAO.deleteUserById(userId);
1✔
284
  }
1✔
285

286
  public List<UserProperty> findAllUserProperties(Integer userId) {
287
    return userPropertyDAO.findUserPropertiesByUserIdAndPropertyKeys(userId,
1✔
288
        UserFields.getValues());
1✔
289
  }
290

291
  public void updateEmailPreference(boolean preference, Integer userId) {
292
    userDAO.updateEmailPreference(userId, preference);
×
293
  }
×
294

295
  public List<SimplifiedUser> findSOsByInstitutionId(Integer institutionId) {
296
    if (Objects.isNull(institutionId)) {
1✔
297
      return Collections.emptyList();
1✔
298
    }
299

300
    List<User> users = userDAO.getSOsByInstitution(institutionId);
1✔
301
    return users.stream().map(SimplifiedUser::new).collect(Collectors.toList());
1✔
302
  }
303

304
  public List<User> findUsersByInstitutionId(Integer institutionId) {
305
    if (Objects.isNull(institutionId)) {
1✔
306
      throw new IllegalArgumentException();
1✔
307
    }
308
    Institution institution = institutionDAO.findInstitutionById(institutionId);
1✔
309
    if (Objects.isNull(institution)) {
1✔
310
      throw new NotFoundException();
×
311
    }
312
    return userDAO.findUsersByInstitution(institutionId);
1✔
313
  }
314

315
  public void deleteUserRole(User authUser, Integer userId, Integer roleId) {
316
    userRoleDAO.removeSingleUserRole(userId, roleId);
×
317
    logInfo(
×
318
        "User %s deleted roleId: %s from User ID: %s".formatted(authUser.getDisplayName(), roleId,
×
319
            userId));
320
  }
×
321

322
  public List<User> findUsersWithNoInstitution() {
323
    return userDAO.getUsersWithNoInstitution();
1✔
324
  }
325

326
  /**
327
   * Convenience method to return a response-friendly json object of the user.
328
   *
329
   * @param authUser The AuthUser. Used to determine if we should return auth user properties
330
   * @param userId   The User. This is the user we want to return properties for
331
   * @return JsonObject.
332
   */
333
  public JsonObject findUserWithPropertiesByIdAsJsonObject(AuthUser authUser, Integer userId) {
334
    Gson gson = GsonUtil.getInstance();
1✔
335
    User user = findUserById(userId);
1✔
336
    List<UserProperty> props = findAllUserProperties(user.getUserId());
1✔
337
    List<LibraryCard> entries =
338
        Objects.nonNull(user.getLibraryCards()) ? user.getLibraryCards() : List.of();
1✔
339
    JsonObject userJson = gson.toJsonTree(user).getAsJsonObject();
1✔
340
    JsonArray propsJson = gson.toJsonTree(props).getAsJsonArray();
1✔
341
    JsonArray entriesJson = gson.toJsonTree(entries).getAsJsonArray();
1✔
342
    userJson.add(USER_PROPERTIES_FIELD, propsJson);
1✔
343
    userJson.add(LIBRARY_CARDS_FIELD, entriesJson);
1✔
344
    if (authUser.getEmail().equalsIgnoreCase(user.getEmail()) && Objects.nonNull(
1✔
345
        authUser.getUserStatusInfo())) {
1✔
346
      JsonObject userStatusInfoJson = gson.toJsonTree(authUser.getUserStatusInfo())
1✔
347
          .getAsJsonObject();
1✔
348
      userJson.add(USER_STATUS_INFO_FIELD, userStatusInfoJson);
1✔
349
    }
350
    return userJson;
1✔
351
  }
352

353
  private void validateRequiredFields(User user) {
354
    if (StringUtils.isEmpty(user.getDisplayName())) {
1✔
355
      throw new BadRequestException("Display Name cannot be empty");
1✔
356
    }
357
    if (StringUtils.isEmpty(user.getEmail())) {
1✔
358
      throw new BadRequestException("Email address cannot be empty");
1✔
359
    }
360
    List<String> validRoleNameList = Stream.of(UserRoles.RESEARCHER, UserRoles.ALUMNI,
1✔
361
        UserRoles.ADMIN).map(UserRoles::getRoleName).toList();
1✔
362
    user.getRoles().forEach(role -> {
1✔
363
      if (!validRoleNameList.contains(role.getName())) {
1✔
364
        String validRoleNames = String.join(", ", validRoleNameList);
1✔
365
        throw new BadRequestException(
1✔
366
            "Invalid role: " + role.getName() + ". Valid roles are: " + validRoleNames);
1✔
367
      }
368
    });
1✔
369
  }
1✔
370

371
  public void insertUserRoles(List<UserRole> roles, Integer userId) {
372
    roles.forEach(r -> {
1✔
373
      if (r.getRoleId() == null) {
1✔
374
        r.setRoleId(userRoleDAO.findRoleIdByName(r.getName()));
×
375
      }
376
    });
1✔
377
    userRoleDAO.insertUserRoles(roles, userId);
1✔
378
  }
1✔
379

380
  private void addExistingLibraryCards(User user) {
381
    List<LibraryCard> libraryCards = libraryCardDAO.findAllLibraryCardsByUserEmail(user.getEmail());
1✔
382

383
    libraryCards
1✔
384
        .forEach(lc -> {
1✔
385
          libraryCardDAO.updateLibraryCardById(
1✔
386
              lc.getId(),
1✔
387
              user.getUserId(),
1✔
388
              lc.getInstitutionId(),
1✔
389
              lc.getEraCommonsId(),
1✔
390
              lc.getUserName(),
1✔
391
              lc.getUserEmail(),
1✔
392
              user.getUserId(),
1✔
393
              new Date());
394
        });
1✔
395
  }
1✔
396

397
  public User findOrCreateUser(AuthUser authUser) throws Exception {
398
    User user;
399
    // Ensure that the user is a registered DUOS user
400
    try {
401
      user = userDAO.findUserByEmail(authUser.getEmail());
1✔
402
    } catch (NotFoundException nfe) {
1✔
403
      User newUser = new User();
1✔
404
      newUser.setEmail(authUser.getEmail());
1✔
405
      newUser.setDisplayName(authUser.getName());
1✔
406
      user = createUser(newUser);
1✔
407
    }
1✔
408
    // Ensure that the user is a registered SAM user
409
    try {
410
      samDAO.postRegistrationInfo(authUser);
1✔
411
    } catch (ConsentConflictException cce) {
×
412
      // no-op in the case of conflicts.
413
    }
1✔
414
    return user;
1✔
415
  }
416

417
  public List<User> findUsersInJsonArray(String json, String arrayKey) {
418
    List<JsonElement> jsonElementList;
419
    try {
420
      JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class);
1✔
421
      jsonElementList = jsonObject.getAsJsonArray(arrayKey).asList();
1✔
422
    } catch (Exception e) {
1✔
423
      throw new BadRequestException("Invalid JSON or missing array with key: " + arrayKey);
1✔
424
    }
1✔
425
    return jsonElementList.stream().distinct().map(e -> findUserById(e.getAsInt())).toList();
1✔
426
  }
427

428
  public void hasValidActiveERACredentials(User user) {
429
    List<LibraryCard> cards = user.getLibraryCards();
1✔
430
    List<UserProperty> userProperties = findAllUserProperties(user.getUserId());
1✔
431
    if (cards.isEmpty()) {
1✔
432
      throw new LibraryCardRequiredException();
1✔
433
    }
434
    boolean hasEraCommonsId = user.getEraCommonsId() != null;
1✔
435
    if (!hasEraCommonsId) {
1✔
436
      throw new BadRequestException("User does not have an Era Commons ID");
1✔
437
    }
438
    List<UserProperty> eraStatusProps = userProperties.stream().filter(
1✔
439
            userProperty -> userProperty.getPropertyKey().equalsIgnoreCase(ERA_STATUS.getValue()))
1✔
440
        .toList();
1✔
441
    List<UserProperty> eraExpirationProps = userProperties.stream().filter(
1✔
442
            userProperty -> userProperty.getPropertyKey()
1✔
443
                .equalsIgnoreCase(ERA_EXPIRATION_DATE.getValue()))
1✔
444
        .toList();
1✔
445
    if (eraStatusProps.size() == 1 && eraExpirationProps.size() == 1) {
1✔
446
      if (!eraStatusProps.get(0).getPropertyValue().equalsIgnoreCase("true")) {
1✔
447
        throw new BadRequestException("User does not have an Era Commons ID that is authorized.");
×
448
      }
449
      if (Instant.ofEpochMilli(Long.parseLong(eraExpirationProps.get(0).getPropertyValue()))
1✔
450
          .isBefore(Instant.now())) {
1✔
451
        throw new BadRequestException("User has an expired Era Commons ID.");
1✔
452
      }
453
    } else {
454
      throw new BadRequestException(
1✔
455
          "Invalid ERA configuration for this user.  Only one ERA Commons ID is allowed.");
456
    }
457
  }
1✔
458

459
  public static class SimplifiedUser {
460

461
    public Integer userId;
462
    public String displayName;
463
    public String email;
464
    public Integer institutionId;
465

466
    public SimplifiedUser(User user) {
1✔
467
      this.userId = user.getUserId();
1✔
468
      this.displayName = user.getDisplayName();
1✔
469
      this.email = user.getEmail();
1✔
470
      this.institutionId = user.getInstitutionId();
1✔
471
    }
1✔
472

473
    public SimplifiedUser() {
1✔
474
    }
1✔
475

476
    public void setUserId(Integer userId) {
477
      this.userId = userId;
1✔
478
    }
1✔
479

480
    public void setDisplayName(String name) {
481
      this.displayName = name;
1✔
482
    }
1✔
483

484
    public void setEmail(String email) {
485
      this.email = email;
1✔
486
    }
1✔
487

488
    public void setInstitutionId(Integer institutionId) {
489
      this.institutionId = institutionId;
×
490
    }
×
491

492
    @Override
493
    public boolean equals(Object o) {
494
      if (this == o) {
1✔
495
        return true;
×
496
      }
497
      if (o == null || getClass() != o.getClass()) {
1✔
498
        return false;
×
499
      }
500
      SimplifiedUser that = (SimplifiedUser) o;
1✔
501
      return Objects.equals(userId, that.userId);
1✔
502
    }
503

504
    @Override
505
    public int hashCode() {
506
      return Objects.hash(userId);
×
507
    }
508
  }
509
}
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