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

DataBiosphere / consent / #4990

17 Apr 2024 02:26PM UTC coverage: 76.054% (+0.2%) from 75.873%
#4990

push

web-flow
[DUOS-2952] POST DAA request API (#2283)

Co-authored-by: Florian Boulnois <fboulnoi@broadinstitute.org>

68 of 69 new or added lines in 10 files covered. (98.55%)

1 existing line in 1 file now uncovered.

9544 of 12549 relevant lines covered (76.05%)

0.76 hits per line

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

96.25
/src/main/java/org/broadinstitute/consent/http/resources/DaaResource.java
1
package org.broadinstitute.consent.http.resources;
2

3
import com.google.inject.Inject;
4
import io.dropwizard.auth.Auth;
5
import jakarta.annotation.security.PermitAll;
6
import jakarta.annotation.security.RolesAllowed;
7
import jakarta.ws.rs.BadRequestException;
8
import jakarta.ws.rs.Consumes;
9
import jakarta.ws.rs.DELETE;
10
import jakarta.ws.rs.GET;
11
import jakarta.ws.rs.POST;
12
import jakarta.ws.rs.PUT;
13
import jakarta.ws.rs.Path;
14
import jakarta.ws.rs.PathParam;
15
import jakarta.ws.rs.Produces;
16
import jakarta.ws.rs.core.Context;
17
import jakarta.ws.rs.core.MediaType;
18
import jakarta.ws.rs.core.Response;
19
import jakarta.ws.rs.core.Response.Status;
20
import jakarta.ws.rs.core.StreamingOutput;
21
import jakarta.ws.rs.core.UriInfo;
22
import java.io.InputStream;
23
import java.net.URI;
24
import java.util.List;
25
import java.util.Optional;
26
import org.broadinstitute.consent.http.enumeration.UserRoles;
27
import org.broadinstitute.consent.http.models.AuthUser;
28
import org.broadinstitute.consent.http.models.DataAccessAgreement;
29
import org.broadinstitute.consent.http.models.LibraryCard;
30
import org.broadinstitute.consent.http.models.User;
31
import org.broadinstitute.consent.http.models.UserRole;
32
import org.broadinstitute.consent.http.service.DaaService;
33
import org.broadinstitute.consent.http.service.DacService;
34
import org.broadinstitute.consent.http.service.EmailService;
35
import org.broadinstitute.consent.http.service.LibraryCardService;
36
import org.broadinstitute.consent.http.service.UserService;
37
import org.broadinstitute.consent.http.service.UserService.SimplifiedUser;
38
import org.broadinstitute.consent.http.util.ConsentLogger;
39
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
40
import org.glassfish.jersey.media.multipart.FormDataParam;
41

42
@Path("api/daa")
43
public class DaaResource extends Resource implements ConsentLogger {
44

45
  private final DaaService daaService;
46
  private final DacService dacService;
47
  private final UserService userService;
48
  private final LibraryCardService libraryCardService;
49
  private final EmailService emailService;
50

51
  @Inject
52
  public DaaResource(DaaService daaService, DacService dacService, UserService userService,
53
      LibraryCardService libraryCardService, EmailService emailService) {
1✔
54
    this.daaService = daaService;
1✔
55
    this.dacService = dacService;
1✔
56
    this.userService = userService;
1✔
57
    this.libraryCardService = libraryCardService;
1✔
58
    this.emailService = emailService;
1✔
59
  }
1✔
60

61
  @POST
62
  @Consumes(MediaType.MULTIPART_FORM_DATA)
63
  @Produces(MediaType.APPLICATION_JSON)
64
  @RolesAllowed({ADMIN, CHAIRPERSON})
65
  @Path("/dac/{dacId}")
66
  public Response createDaaForDac(
67
      @Context UriInfo info,
68
      @Auth AuthUser authUser,
69
      @PathParam("dacId") Integer dacId,
70
      @FormDataParam("file") InputStream uploadInputStream,
71
      @FormDataParam("file") FormDataContentDisposition fileDetail) {
72
    try {
73
      validateFileDetails(fileDetail);
1✔
74
      dacService.findById(dacId);
1✔
75
      User user = userService.findUserByEmail(authUser.getEmail());
1✔
76
      // Assert that the user has the correct DAC permissions to add a DAA for the provided DacId.
77
      // Admins can add a DAA with any DAC, but chairpersons can only add DAAs for DACs they are a
78
      // chairperson for.
79
      if (!user.hasUserRole(UserRoles.ADMIN)) {
1✔
80
        List<Integer> dacIds = user.getRoles().stream().map(UserRole::getDacId).toList();
1✔
81
        if (!dacIds.contains(dacId)) {
1✔
82
          return Response.status(Status.FORBIDDEN).build();
1✔
83
        }
84
      }
85
      DataAccessAgreement daa = daaService.createDaaWithFso(user.getUserId(), dacId,
1✔
86
          uploadInputStream, fileDetail);
87
      URI uri = info.getBaseUriBuilder()
1✔
88
          // This will be the GET endpoint for the created DAA
89
          .replacePath("api/daa/{daaId}")
1✔
90
          .build(daa.getDaaId());
1✔
91
      return Response.created(uri).entity(daa).build();
1✔
92
    } catch (Exception e) {
1✔
93
      return createExceptionResponse(e);
1✔
94
    }
95
  }
96

97
  @PUT
98
  @Produces(MediaType.APPLICATION_JSON)
99
  @RolesAllowed({ADMIN, SIGNINGOFFICIAL})
100
  @Path("{daaId}/{userId}")
101
  public Response createLibraryCardDaaRelation(
102
      @Context UriInfo info,
103
      @Auth AuthUser authUser,
104
      @PathParam("daaId") Integer daaId,
105
      @PathParam("userId") Integer userId) {
106
    try {
107
      User authedUser = userService.findUserByEmail(authUser.getEmail());
1✔
108
      int authedUserInstitutionId = authedUser.getInstitutionId();
1✔
109
      User user = userService.findUserById(userId);
1✔
110
      int userInstitutionId = user.getInstitutionId();
1✔
111
      // Assert that the user has the correct institution permissions to add a DAA-LC relationship.
112
      // Admins can add a DAA with any DAC, but signing officials can only create relationships for
113
      // library cards associated with the same institution they are associated with.
114
      if (!authedUser.hasUserRole(UserRoles.ADMIN) && !authedUser.hasUserRole(UserRoles.SIGNINGOFFICIAL)) {
1✔
115
        return Response.status(Status.FORBIDDEN).build();
1✔
116
      } else if (authedUser.hasUserRole(UserRoles.SIGNINGOFFICIAL) && authedUserInstitutionId != userInstitutionId) {
1✔
117
          return Response.status(Status.FORBIDDEN).build();
1✔
118
      }
119
      List<LibraryCard> libraryCards = libraryCardService.findLibraryCardsByUserId(userId);
1✔
120
      Optional<LibraryCard> matchingCard = libraryCards.stream()
1✔
121
          .filter(card -> card.getInstitutionId() == authedUser.getInstitutionId().intValue())
1✔
122
          .findFirst();
1✔
123
      if (matchingCard.isEmpty()) {
1✔
124
        return Response.status(Status.NOT_FOUND).build();
1✔
125
      }
126
      int libraryCardId = matchingCard.get().getId();
1✔
127
      libraryCardService.addDaaToLibraryCard(libraryCardId, daaId);
1✔
128
      URI uri = info.getBaseUriBuilder()
1✔
129
          .replacePath("api/libraryCards/{libraryCardId}")
1✔
130
          .build(libraryCardId);
1✔
131
      return Response.ok().location(uri).entity(matchingCard.get()).build();
1✔
132
    } catch (Exception e) {
1✔
133
      return createExceptionResponse(e);
1✔
134
    }
135
  }
136

137
  @GET
138
  @Produces(MediaType.APPLICATION_JSON)
139
  @PermitAll
140
  public Response findAll() {
141
    try {
142
      List<DataAccessAgreement> daas = daaService.findAll();
1✔
143
      return Response.ok(daas).build();
1✔
144
    } catch (Exception e) {
×
145
      return createExceptionResponse(e);
×
146
    }
147
  }
148

149
  @GET
150
  @Produces(MediaType.APPLICATION_JSON)
151
  @RolesAllowed({ADMIN, MEMBER, CHAIRPERSON, RESEARCHER})
152
  @Path("{daaId}")
153
  public Response findById(
154
      @PathParam("daaId") Integer daaId) {
155
    try {
156
      DataAccessAgreement daa = daaService.findById(daaId);
1✔
157
      return Response.ok(daa).build();
1✔
158
    } catch (Exception e) {
1✔
159
      return createExceptionResponse(e);
1✔
160
    }
161
  }
162

163
  @GET
164
  @PermitAll
165
  @Path("{daaId}/file")
166
  @Produces({MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON})
167
  public Response findFileById(
168
      @PathParam("daaId") Integer daaId) {
169
    try {
170
      InputStream daa = daaService.findFileById(daaId);
1✔
171
      StreamingOutput stream = createStreamingOutput(daa);
1✔
172
      DataAccessAgreement daa2 = daaService.findById(daaId);
1✔
173
      String fileName = daa2.getFile().getFileName();
1✔
174
      return Response.ok(stream)
1✔
175
          .header("Content-Disposition", "attachment; filename=" + fileName)
1✔
176
          .build();
1✔
177
    } catch (Exception e) {
1✔
178
      return createExceptionResponse(e);
1✔
179
    }
180
  }
181

182
  @DELETE
183
  @RolesAllowed({ADMIN, SIGNINGOFFICIAL})
184
  @Path("{daaId}/{userId}")
185
  public Response deleteDaaForUser(
186
      @Auth AuthUser authUser,
187
      @PathParam("daaId") Integer daaId,
188
      @PathParam("userId") Integer userId) {
189
    try {
190
      User user = userService.findUserByEmail(authUser.getEmail());
1✔
191
      if (!user.hasUserRole(UserRoles.ADMIN)) {
1✔
192
        return Response.status(Status.FORBIDDEN).build();
1✔
193
      }
194
      List<LibraryCard> libraryCards = libraryCardService.findLibraryCardsByUserId(userId);
1✔
195
      for (LibraryCard libraryCard : libraryCards) {
1✔
196
        libraryCardService.removeDaaFromLibraryCard(libraryCard.getId(), daaId);
1✔
197
      }
1✔
198
      return Response.ok().build();
1✔
199
    } catch (Exception e) {
1✔
200
      return createExceptionResponse(e);
1✔
201
    }
202
  }
203

204
  @POST
205
  @PermitAll
206
  @Path("/request/{daaId}")
207
  public Response sendDaaRequestMessage(
208
      @Auth AuthUser authUser,
209
      @PathParam("daaId") Integer daaId) {
210
    try {
211
      User user = userService.findUserByEmail(authUser.getEmail());
1✔
212
      if (user.getInstitutionId() == null) {
1✔
213
        throw new BadRequestException("This user has not set their institution: " + user.getDisplayName());
1✔
214
      }
215
      if (user.getLibraryCards().stream()
1✔
216
          .anyMatch(libraryCard -> libraryCard.getDaaIds().contains(daaId))) {
1✔
NEW
217
        throw new IllegalArgumentException("User already has this DAA associated with their Library Card");
×
218
      }
219
      daaService.sendDaaRequestEmails(user, daaId);
1✔
220
      return Response.ok().build();
1✔
221
    } catch (Exception e) {
1✔
222
      return createExceptionResponse(e);
1✔
223
    }
224
  }
225
}
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