Skip to content

Commit

Permalink
[DUOS-2196][risk=low] Initial Acknowledgement Service implementation. (
Browse files Browse the repository at this point in the history
…#1813)

* Initial Acknowledgement Service implementation.
  • Loading branch information
otchet-broad authored Nov 16, 2022
1 parent c25b633 commit cca5793
Show file tree
Hide file tree
Showing 21 changed files with 816 additions and 120 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.broadinstitute.consent.http.resources.UserResource;
import org.broadinstitute.consent.http.resources.VersionResource;
import org.broadinstitute.consent.http.resources.VoteResource;
import org.broadinstitute.consent.http.service.AcknowledgementService;
import org.broadinstitute.consent.http.service.AuditService;
import org.broadinstitute.consent.http.service.ConsentService;
import org.broadinstitute.consent.http.service.DacService;
Expand Down Expand Up @@ -193,6 +194,7 @@ public void run(ConsentConfiguration config, Environment env) {
final SamService samService = injector.getProvider(SamService.class).get();
final SupportRequestService supportRequestService = injector.getProvider(SupportRequestService.class).get();
final TDRService tdrService = injector.getProvider(TDRService.class).get();
final AcknowledgementService acknowledgementService = injector.getProvider(AcknowledgementService.class).get();

System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
configureCors(env);
Expand Down Expand Up @@ -247,7 +249,7 @@ public void run(ConsentConfiguration config, Environment env) {
env.jersey().register(new SchemaResource());
env.jersey().register(new SwaggerResource(config.getGoogleAuthentication()));
env.jersey().register(new StatusResource(env.healthChecks()));
env.jersey().register(new UserResource(samService, userService, datasetService, supportRequestService));
env.jersey().register(new UserResource(samService, userService, datasetService, supportRequestService, acknowledgementService));
env.jersey().register(new TosResource(samService));
env.jersey().register(injector.getInstance(VersionResource.class));
env.jersey().register(new VoteResource(userService, voteService, electionService));
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/broadinstitute/consent/http/ConsentModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.broadinstitute.consent.http.cloudstore.GCSService;
import org.broadinstitute.consent.http.cloudstore.GCSStore;
import org.broadinstitute.consent.http.configurations.ConsentConfiguration;
import org.broadinstitute.consent.http.db.AcknowledgementDAO;
import org.broadinstitute.consent.http.db.ConsentAuditDAO;
import org.broadinstitute.consent.http.db.ConsentDAO;
import org.broadinstitute.consent.http.db.CounterDAO;
Expand All @@ -33,6 +34,7 @@
import org.broadinstitute.consent.http.db.VoteDAO;
import org.broadinstitute.consent.http.mail.SendGridAPI;
import org.broadinstitute.consent.http.mail.freemarker.FreeMarkerTemplateHelper;
import org.broadinstitute.consent.http.service.AcknowledgementService;
import org.broadinstitute.consent.http.service.AuditService;
import org.broadinstitute.consent.http.service.ConsentService;
import org.broadinstitute.consent.http.service.CounterService;
Expand Down Expand Up @@ -95,6 +97,7 @@ public class ConsentModule extends AbstractModule {
private final DarCollectionSummaryDAO darCollectionSummaryDAO;
private final InstitutionDAO institutionDAO;
private final LibraryCardDAO libraryCardDAO;
private final AcknowledgementDAO acknowledgementDAO;

public static final String DB_ENV = "postgresql";

Expand Down Expand Up @@ -128,6 +131,7 @@ public class ConsentModule extends AbstractModule {
this.darCollectionSummaryDAO = this.jdbi.onDemand(DarCollectionSummaryDAO.class);
this.institutionDAO = this.jdbi.onDemand((InstitutionDAO.class));
this.libraryCardDAO = this.jdbi.onDemand((LibraryCardDAO.class));
this.acknowledgementDAO = this.jdbi.onDemand((AcknowledgementDAO.class));
}

@Override
Expand Down Expand Up @@ -156,6 +160,7 @@ public DAOContainer providesDAOContainer() {
container.setUserRoleDAO(providesUserRoleDAO());
container.setVoteDAO(providesVoteDAO());
container.setInstitutionDAO(providesInstitutionDAO());
container.setAcknowledgementDAO(providesAcknowledgementDAO());
return container;
}

Expand Down Expand Up @@ -491,6 +496,9 @@ InstitutionDAO providesInstitutionDAO() {
@Provides
LibraryCardDAO providesLibraryCardDAO() { return libraryCardDAO; }

@Provides
AcknowledgementDAO providesAcknowledgementDAO() { return acknowledgementDAO; }

@Provides
InstitutionService providesInstitutionService() {
return new InstitutionService(providesInstitutionDAO(), providesUserDAO());
Expand All @@ -504,6 +512,13 @@ LibraryCardService providesLibraryCardService() {
providesUserDAO());
}

@Provides
AcknowledgementService providesAcknowledgementService() {
return new AcknowledgementService(
providesAcknowledgementDAO()
);
}

@Provides
UserService providesUserService() {
return new UserService(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.broadinstitute.consent.http.db;

import org.broadinstitute.consent.http.db.mapper.AcknowledgementMapper;
import org.broadinstitute.consent.http.models.Acknowledgement;
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
import org.jdbi.v3.sqlobject.customizer.Bind;
import org.jdbi.v3.sqlobject.customizer.BindList;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import org.jdbi.v3.sqlobject.transaction.Transactional;

import java.util.List;

@RegisterRowMapper(AcknowledgementMapper.class)
public interface AcknowledgementDAO extends Transactional<AcknowledgementDAO> {

@SqlUpdate("INSERT INTO acknowledgement (ack_key, user_id, first_acknowledged, last_acknowledged) "
+ " VALUES (:key, :userId, current_timestamp, current_timestamp) "
+ " ON CONFLICT (ack_key, user_id) DO UPDATE SET last_acknowledged = current_timestamp ")
void upsertAcknowledgement(@Bind("key") String key, @Bind("userId") Integer userId);

@SqlQuery("SELECT ack_key, user_id, first_acknowledged, last_acknowledged "
+ " FROM acknowledgement WHERE ack_key = :key and user_id = :userId")
Acknowledgement findAcknowledgementsByKeyForUser(@Bind("key") String key, @Bind("userId") Integer userId);

@SqlQuery("SELECT ack_key, user_id, first_acknowledged, last_acknowledged "
+ " FROM acknowledgement WHERE user_id = :userId")
List<Acknowledgement> findAcknowledgementsForUser(@Bind("userId") Integer userId);

@SqlQuery("SELECT ack_key, user_id, first_acknowledged, last_acknowledged "
+ " FROM acknowledgement WHERE user_id = :userId and ack_key IN (<key_list>)")
List<Acknowledgement> findAcknowledgementsForUser(@BindList("key_list") List<String> keys, @Bind("userId") Integer userId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class DAOContainer {
private VoteDAO voteDAO;
private ConsentAuditDAO consentAuditDAO;
private InstitutionDAO institutionDAO;
private AcknowledgementDAO acknowledgementDAO;

public ConsentDAO getConsentDAO() {
return consentDAO;
Expand Down Expand Up @@ -162,4 +163,12 @@ public void setConsentAuditDAO(ConsentAuditDAO consentAuditDAO) {
public InstitutionDAO getInstitutionDAO() { return institutionDAO; }

public void setInstitutionDAO(InstitutionDAO institutionDAO) { this.institutionDAO = institutionDAO; }

public AcknowledgementDAO getAcknowledgementDAO() {
return acknowledgementDAO;
}

public void setAcknowledgementDAO(AcknowledgementDAO acknowledgementDAO) {
this.acknowledgementDAO = acknowledgementDAO;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.broadinstitute.consent.http.db.mapper;

import org.broadinstitute.consent.http.models.Acknowledgement;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.statement.StatementContext;

import java.sql.ResultSet;
import java.sql.SQLException;

public class AcknowledgementMapper implements RowMapper<Acknowledgement> {
@Override
public Acknowledgement map(ResultSet rs, StatementContext ctx) throws SQLException {
Acknowledgement ack = new Acknowledgement();
ack.setAckKey(rs.getString("ack_key"));
ack.setUserId(rs.getInt("user_id"));
ack.setFirstAcknowledged(rs.getTimestamp("first_acknowledged"));
ack.setLastAcknowledged(rs.getTimestamp("last_acknowledged"));
return ack;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.broadinstitute.consent.http.models;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Objects;

public class Acknowledgement {

private String ackKey;
private Integer userId;
private Timestamp firstAcknowledged;
private Timestamp lastAcknowledged;

public Integer getUserId() {
return userId;
}

public void setUserId(Integer userId) {
this.userId = userId;
}

public Date getFirstAcknowledged() { return firstAcknowledged; }

public void setFirstAcknowledged(Timestamp firstAcknowledged) {
this.firstAcknowledged = firstAcknowledged;
}

public Date getLastAcknowledged() {
return lastAcknowledged;
}

public void setLastAcknowledged(Timestamp lastAcknowledged) {
this.lastAcknowledged = lastAcknowledged;
}

public String getAckKey() {
return ackKey;
}

public void setAckKey(String ackKey) {
this.ackKey = ackKey;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Acknowledgement ack = (Acknowledgement) o;
return (Objects.equals(this.getAckKey(), ack.getAckKey()) &&
Objects.equals(this.getUserId(), ack.getUserId()) &&
this.getLastAcknowledged().getTime() == (ack.getLastAcknowledged().getTime()) &&
this.getFirstAcknowledged().getTime() == (ack.getFirstAcknowledged()).getTime());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@

import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.*;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@
import com.google.api.client.http.HttpStatusCodes;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import io.dropwizard.auth.Auth;
import org.broadinstitute.consent.http.authentication.GoogleUser;
import org.broadinstitute.consent.http.enumeration.UserRoles;
import org.broadinstitute.consent.http.models.Acknowledgement;
import org.broadinstitute.consent.http.models.AuthUser;
import org.broadinstitute.consent.http.models.User;
import org.broadinstitute.consent.http.models.UserRole;
import org.broadinstitute.consent.http.models.UserUpdateFields;
import org.broadinstitute.consent.http.models.dto.DatasetDTO;
import org.broadinstitute.consent.http.models.dto.Error;
import org.broadinstitute.consent.http.service.AcknowledgementService;
import org.broadinstitute.consent.http.service.DatasetService;
import org.broadinstitute.consent.http.service.SupportRequestService;
import org.broadinstitute.consent.http.service.UserService;
Expand All @@ -36,9 +39,12 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -51,14 +57,17 @@ public class UserResource extends Resource {
private final SamService samService;
private final DatasetService datasetService;
private final SupportRequestService supportRequestService;
private final AcknowledgementService acknowledgementService;

@Inject
public UserResource(SamService samService, UserService userService,
DatasetService datasetService, SupportRequestService supportRequestService) {
DatasetService datasetService, SupportRequestService supportRequestService,
AcknowledgementService acknowledgementService) {
this.samService = samService;
this.userService = userService;
this.datasetService = datasetService;
this.supportRequestService = supportRequestService;
this.acknowledgementService = acknowledgementService;
}

@GET
Expand Down Expand Up @@ -333,4 +342,61 @@ public Response getSOsForInstitution(@Auth AuthUser authUser) {
return createExceptionResponse(e);
}
}

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/acknowledgements")
@PermitAll
public Response getUserAcknowledgements(@Auth AuthUser authUser) {
try {
User user = userService.findUserByEmail(authUser.getEmail());
Map<String, Acknowledgement> acknowledgementMap = acknowledgementService.findAcknowledgementsForUser(user);
return Response.ok().entity(acknowledgementMap).build();
} catch (Exception e) {
return createExceptionResponse(e);
}
}

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/acknowledgements/{key}")
@PermitAll
public Response getUserAcknowledgement(@Auth AuthUser authUser, @PathParam("key") String key){
try {
User user = userService.findUserByEmail(authUser.getEmail());
Acknowledgement ack = acknowledgementService.findAcknowledgementForUserByKey(user, key);
if (ack == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok().entity(ack).build();
} catch (Exception e) {
return createExceptionResponse(e);
}
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/acknowledgements")
@PermitAll
public Response postAcknowledgements(@Auth AuthUser authUser, String json) {
ArrayList<String> keys;
try {
Type listOfStringsType = new TypeToken<ArrayList<String>>() {}.getType();
keys = gson.fromJson(json, listOfStringsType);
if (keys == null || keys.isEmpty()){
return Response.status(Response.Status.BAD_REQUEST).build();
}
} catch (Exception e) {
return Response.status(Response.Status.BAD_REQUEST).build();
}

try{
User user = userService.findUserByEmail(authUser.getEmail());
Map<String, Acknowledgement> acknowledgementMap = acknowledgementService.makeAcknowledgements(keys, user);
return Response.ok().entity(acknowledgementMap).build();
} catch (Exception e){
return createExceptionResponse(e);
}
}
}
Loading

0 comments on commit cca5793

Please sign in to comment.