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

DataBiosphere / consent / #6189

08 Jul 2025 08:49PM UTC coverage: 80.64% (+0.01%) from 80.63%
#6189

push

web-flow
DT-1936: New API to import allow list (#2601)

19 of 22 new or added lines in 1 file covered. (86.36%)

10430 of 12934 relevant lines covered (80.64%)

0.81 hits per line

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

92.31
/src/main/java/org/broadinstitute/consent/http/resources/InstitutionResource.java
1
package org.broadinstitute.consent.http.resources;
2

3
import com.google.gson.Gson;
4
import com.google.inject.Inject;
5
import io.dropwizard.auth.Auth;
6
import jakarta.annotation.security.PermitAll;
7
import jakarta.annotation.security.RolesAllowed;
8
import jakarta.ws.rs.Consumes;
9
import jakarta.ws.rs.DELETE;
10
import jakarta.ws.rs.GET;
11
import jakarta.ws.rs.PATCH;
12
import jakarta.ws.rs.POST;
13
import jakarta.ws.rs.PUT;
14
import jakarta.ws.rs.Path;
15
import jakarta.ws.rs.PathParam;
16
import jakarta.ws.rs.Produces;
17
import jakarta.ws.rs.core.Response;
18
import java.util.ArrayList;
19
import java.util.List;
20
import org.broadinstitute.consent.http.exceptions.ConsentConflictException;
21
import org.broadinstitute.consent.http.models.DuosUser;
22
import org.broadinstitute.consent.http.models.Institution;
23
import org.broadinstitute.consent.http.models.InstitutionDomainMap;
24
import org.broadinstitute.consent.http.service.InstitutionService;
25
import org.broadinstitute.consent.http.util.InstitutionUtil;
26
import org.broadinstitute.consent.http.util.gson.GsonUtil;
27

28
@Path("api/institutions")
29
public class InstitutionResource extends Resource {
30

31
  private final InstitutionService institutionService;
32
  /*
33
    NOTE: InstitutionUtil will provide a configured GsonBuilder to help format the JSON response.
34
    Response needs to be filtered based on user roles (Admins would see all, non-admins would not)
35
    As such, any @PermitAll route would require the entity (Institution) to be formatted with the GsonBuilder
36
    as opposed to being passed into the response directly.
37
  */
38
  private final InstitutionUtil institutionUtil = new InstitutionUtil();
1✔
39

40
  @Inject
41
  public InstitutionResource(InstitutionService institutionService) {
1✔
42
    this.institutionService = institutionService;
1✔
43
  }
1✔
44

45
  @GET
46
  @Produces("application/json")
47
  @PermitAll
48
  public Response getInstitutions(@Auth DuosUser duosUser) {
49
    try {
50
      Boolean isAdmin = institutionUtil.checkIfAdmin(duosUser.getUser());
1✔
51
      Gson gson = institutionUtil.getGsonBuilder(isAdmin);
1✔
52
      List<Institution> institutions = institutionService.findAllInstitutions();
1✔
53
      return Response.ok().entity(gson.toJson(institutions)).build();
1✔
54
    } catch (Exception e) {
×
55
      return createExceptionResponse(e);
×
56
    }
57
  }
58

59
  @GET
60
  @Produces("application/json")
61
  @Path("/{id}")
62
  @PermitAll
63
  public Response getInstitution(@Auth DuosUser duosUser, @PathParam("id") Integer id) {
64
    try {
65
      Boolean isAdmin = institutionUtil.checkIfAdmin(duosUser.getUser());
1✔
66
      Gson gson = institutionUtil.getGsonBuilder(isAdmin);
1✔
67
      Institution institution = institutionService.findInstitutionById(id);
1✔
68
      return Response.ok().entity(gson.toJson(institution)).build();
1✔
69
    } catch (Exception e) {
1✔
70
      return createExceptionResponse(e);
1✔
71
    }
72
  }
73

74
  @POST
75
  @Consumes("application/json")
76
  @Produces("application/json")
77
  @RolesAllowed(ADMIN)
78
  public Response createInstitution(@Auth DuosUser duosUser, String institution) {
79
    try {
80
      Institution payload = GsonUtil.getInstance().fromJson(institution, Institution.class);
1✔
81
      List<Institution> conflicts = institutionService.findAllInstitutionsByName(payload.getName());
1✔
82
      if (!conflicts.isEmpty()) {
1✔
83
        throw new ConsentConflictException(
1✔
84
            "An institution exists with the name of '" + payload.getName() + "'");
1✔
85
      }
86
      Institution newInstitution = institutionService.createInstitution(payload, duosUser.getUser().getUserId());
1✔
87
      return Response.ok().entity(newInstitution).build();
1✔
88
    } catch (Exception e) {
1✔
89
      return createExceptionResponse(e);
1✔
90
    }
91
  }
92

93
  @PATCH
94
  @Consumes("application/json")
95
  @Produces("application/json")
96
  @Path("/{id}")
97
  @RolesAllowed(ADMIN)
98
  public Response patchInstitution(@Auth DuosUser duosUser, @PathParam("id") Integer id,
99
      String institution) {
100
    try {
101
      Institution existingInstitution = institutionService.findInstitutionById(id);
1✔
102
      Institution payload = GsonUtil.getInstance().fromJson(institution, Institution.class);
1✔
103
      Institution mergedPayload = payload.mergeUpdatableFields(existingInstitution);
1✔
104
      Institution updatedInstitution = institutionService.updateInstitutionById(mergedPayload, id,
1✔
105
          duosUser.getUserId());
1✔
106
      return Response.ok().entity(updatedInstitution).build();
1✔
107
    } catch (Exception e) {
1✔
108
      return createExceptionResponse(e);
1✔
109
    }
110
  }
111

112
  @PUT
113
  @Consumes("application/json")
114
  @Produces("application/json")
115
  @Path("/{id}")
116
  @RolesAllowed(ADMIN)
117
  public Response updateInstitution(@Auth DuosUser duosUser, @PathParam("id") Integer id,
118
      String institution) {
119
    try {
120
      Institution payload = GsonUtil.getInstance().fromJson(institution, Institution.class);
1✔
121
      Institution updatedInstitution = institutionService.updateInstitutionById(payload, id,
1✔
122
          duosUser.getUserId());
1✔
123
      return Response.ok().entity(updatedInstitution).build();
1✔
124
    } catch (Exception e) {
1✔
125
      return createExceptionResponse(e);
1✔
126
    }
127
  }
128

129
  @DELETE
130
  @Produces("application/json")
131
  @Path("/{id}")
132
  @RolesAllowed(ADMIN)
133
  public Response deleteInstitution(@Auth DuosUser duosUser, @PathParam("id") Integer id) {
134
    try {
135
      institutionService.deleteInstitutionById(id);
1✔
136
      return Response.status(204).build();
1✔
137
    } catch (Exception e) {
1✔
138
      return createExceptionResponse(e);
1✔
139
    }
140
  }
141

142
  @POST
143
  @Consumes("application/json")
144
  @Produces("application/json")
145
  @Path("/domains")
146
  @RolesAllowed(ADMIN)
147
  public Response updateInstitutionDomains(@Auth DuosUser duosUser, String institutionDomainMap) {
148
    try {
149
      List<Institution> updatedInstitutions = new ArrayList<>();
1✔
150
      InstitutionDomainMap domainMap = GsonUtil.getInstance().fromJson(institutionDomainMap, InstitutionDomainMap.class);
1✔
151
      domainMap.getInstitutionDomainMap().forEach((institutionName, value) -> {
1✔
152
        List<String> domains = value.stream().toList();
1✔
153
        List<Institution> institutions = institutionService.findAllInstitutionsByName(
1✔
154
            institutionName);
155
        if (institutions.isEmpty()) {
1✔
156
          logWarn("No institution found with name: [%s]".formatted(institutionName));
1✔
157
        } else if (institutions.size() == 1) {
1✔
158
          Institution institution = institutions.get(0);
1✔
159
          institution.setDomains(domains);
1✔
160
          try {
161
            updatedInstitutions.add(institutionService.updateInstitutionById(
1✔
162
                institution,
163
                institution.getId(),
1✔
164
                duosUser.getUserId()));
1✔
NEW
165
          } catch (Exception e) {
×
NEW
166
            logException("Failed to update institution: [%s] with domains: %s".formatted(institutionName, domains), e);
×
167
          }
1✔
168
        } else {
1✔
NEW
169
          logWarn("Multiple institutions found with name: [%s]".formatted(institutionName));
×
170
        }
171
      });
1✔
172
      return Response.ok(updatedInstitutions).build();
1✔
173
    } catch (Exception e) {
1✔
174
      return createExceptionResponse(e);
1✔
175
    }
176
  }
177
}
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