Skip to content

Commit

Permalink
Refactors to introduce DraftServiceDAO and DraftFileStorageServiceDAO…
Browse files Browse the repository at this point in the history
… so that two level mocks aren't needed for GCSService
  • Loading branch information
otchet-broad committed Feb 5, 2025
1 parent e47d249 commit 81b01e2
Show file tree
Hide file tree
Showing 11 changed files with 493 additions and 393 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
import org.broadinstitute.consent.http.service.DatasetRegistrationService;
import org.broadinstitute.consent.http.service.DatasetService;
import org.broadinstitute.consent.http.service.DraftService;
import org.broadinstitute.consent.http.service.dao.DraftServiceDAO;
import org.broadinstitute.consent.http.service.ElasticSearchService;
import org.broadinstitute.consent.http.service.ElectionService;
import org.broadinstitute.consent.http.service.EmailService;
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/org/broadinstitute/consent/http/ConsentModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
import org.broadinstitute.consent.http.service.DataAccessRequestService;
import org.broadinstitute.consent.http.service.DatasetRegistrationService;
import org.broadinstitute.consent.http.service.DatasetService;
import org.broadinstitute.consent.http.service.DraftFileStorageService;
import org.broadinstitute.consent.http.service.DraftService;
import org.broadinstitute.consent.http.service.dao.DraftFileStorageServiceDAO;
import org.broadinstitute.consent.http.service.dao.DraftServiceDAO;
import org.broadinstitute.consent.http.service.ElasticSearchService;
import org.broadinstitute.consent.http.service.ElectionService;
import org.broadinstitute.consent.http.service.EmailService;
Expand Down Expand Up @@ -628,14 +628,14 @@ DraftDAO providesDraftDAO() {
}

@Provides
DraftFileStorageService providesDraftFileStorageService() {
return new DraftFileStorageService(providesJdbi(), providesGCSService(),
DraftFileStorageServiceDAO providesDraftFileStorageService() {
return new DraftFileStorageServiceDAO(providesJdbi(), providesGCSService(),
providesFileStorageObjectDAO());
}

@Provides
DraftService providesDraftService() {
return new DraftService(providesJdbi(), providesDraftDAO(),
DraftServiceDAO providesDraftService() {
return new DraftServiceDAO(providesJdbi(), providesDraftDAO(),
providesDraftFileStorageService());
}
}
170 changes: 36 additions & 134 deletions src/main/java/org/broadinstitute/consent/http/service/DraftService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,173 +2,75 @@

import com.google.gson.Gson;
import com.google.inject.Inject;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.NotAuthorizedException;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.StreamingOutput;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import org.broadinstitute.consent.http.db.DraftDAO;
import org.broadinstitute.consent.http.enumeration.UserRoles;
import org.broadinstitute.consent.http.cloudstore.GCSService;
import org.broadinstitute.consent.http.models.DraftInterface;
import org.broadinstitute.consent.http.models.DraftSummary;
import org.broadinstitute.consent.http.models.FileStorageObject;
import org.broadinstitute.consent.http.models.User;
import org.broadinstitute.consent.http.service.dao.DraftServiceDAO;
import org.broadinstitute.consent.http.util.ConsentLogger;
import org.broadinstitute.consent.http.util.gson.GsonUtil;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.jdbi.v3.core.Jdbi;

public class DraftService {

private final Jdbi jdbi;
private final DraftDAO draftDAO;
private final DraftFileStorageService draftFileStorageService;
public class DraftService implements ConsentLogger {
DraftServiceDAO draftServiceDAO;
GCSService gcsService;

@Inject
public DraftService(Jdbi jdbi, DraftDAO draftDAO,
DraftFileStorageService draftFileStorageService) {
this.jdbi = jdbi;
this.draftDAO = draftDAO;
this.draftFileStorageService = draftFileStorageService;
}

public void insertDraft(DraftInterface draft)
throws SQLException, BadRequestException {
jdbi.useHandle(handle -> {
handle.getConnection().setAutoCommit(false);
try {
draftDAO.insert(draft.getName(), draft.getCreateDate().toInstant(),
draft.getCreateUser().getUserId(), draft.getJson(), draft.getUUID(),
draft.getType().getValue());
} catch (Exception e) {
handle.rollback();
throw new BadRequestException(
"Error submitting draft. Drafts require valid json to be submitted.");
}
handle.commit();
});
}

public DraftInterface updateDraft(DraftInterface draft, User user) throws SQLException {
draft.setUpdateUser(user);
draft.setUpdateDate(new Date());
jdbi.useHandle(handle -> {
handle.getConnection().setAutoCommit(false);
try {
draftDAO.updateDraftByDraftUUID(draft.getName(),
draft.getUpdateDate().toInstant(), draft.getUpdateUser().getUserId(), draft.getJson(),
draft.getUUID(), draft.getType().getValue());
} catch (Exception e) {
handle.rollback();
}
handle.commit();
});
return getAuthorizedDraft(draft.getUUID(), user);
public DraftService(DraftServiceDAO draftServiceDAO, GCSService gcsService) {
this.draftServiceDAO = draftServiceDAO;
this.gcsService = gcsService;
}

public DraftInterface getAuthorizedDraft(UUID draftUUID, User user) {
DraftInterface draft;
try {
draft = findDraftByDraftUUID(draftUUID);
} catch (SQLException e) {
throw new NotFoundException(
String.format("Draft with UUID %s not found.", draftUUID.toString()));
}
if (Objects.isNull(draft)) {
throw new NotFoundException(
String.format("Draft with UUID %s not found.", draftUUID.toString()));
}
if (!user.getUserId().equals(draft.getCreateUser().getUserId()) && !user.hasUserRole(
UserRoles.ADMIN)) {
throw new NotAuthorizedException("User not authorized to modify resource.");
}
return draft;
public DraftInterface getAuthorizedDraft(UUID uuid, User user) {
return draftServiceDAO.getAuthorizedDraft(uuid, user);
}

public void deleteDraftsByUser(User user) {
Set<DraftInterface> userDrafts = findDraftsForUser(user);
for (DraftInterface draft : userDrafts) {
deleteDraft(draft, user);
}
}

public Set<DraftSummary> findDraftSummariesForUser(User user) {
return draftDAO.findDraftSummariesByUserId(user.getUserId());
public List<FileStorageObject> addAttachments(DraftInterface draft, User user, Map<String, FormDataBodyPart> files)
throws SQLException {
return draftServiceDAO.addAttachments(draft, user, files);
}

public Set<DraftInterface> findDraftsForUser(User user) {
return draftDAO.findDraftsByUserId(user.getUserId());
public InputStream getDraftAttachmentStream(FileStorageObject targetAttachment) {
return gcsService.getDocument(targetAttachment.getBlobId());
}

private DraftInterface findDraftByDraftUUID(
UUID draftUUID) throws SQLException {
return draftDAO.findDraftById(draftUUID);
public void deleteDraftAttachment(DraftInterface draft, User user, Integer fileId)
throws SQLException {
draftServiceDAO.deleteDraftAttachment(draft, user, fileId);
}

public List<FileStorageObject> addAttachments(DraftInterface draft, User user,
Map<String, FormDataBodyPart> files) throws SQLException {
List<FileStorageObject> storedFiles = draftFileStorageService.storeDraftFiles(draft.getUUID(), user, files);
draftDAO.updateDraftByDraftUUID(draft.getUUID(),
new Date().toInstant(), user.getUserId());
return storedFiles;
public StreamingOutput draftAsJson(DraftInterface draft) {
Gson gson = GsonUtil.buildGson();
return output -> {
output.write("{ \"document\":".getBytes());
output.write(draft.getJson().getBytes());
output.write(", \"meta\":".getBytes());
output.write(gson.toJson(draft).getBytes());
output.write("}".getBytes());
};
}

public void deleteDraftAttachment(DraftInterface draft, User user, Integer fileId)
throws SQLException {
Optional<FileStorageObject> fileStorageObjectToDelete = draft.getStoredFiles().stream()
.filter(fileStorageObject -> fileStorageObject.getFileStorageObjectId().equals(fileId))
.findFirst();
if (fileStorageObjectToDelete.isPresent()) {
draftFileStorageService.deleteStoredFile(fileStorageObjectToDelete.get(), user);
draftDAO.updateDraftByDraftUUID(draft.getUUID(),
new Date().toInstant(), user.getUserId());
} else {
throw new NotFoundException(
String.format("Draft attachment is not found. Draft: %s, Attachment: %d",
draft.getUUID(), fileId));
}
public void insertDraft(DraftInterface draft) throws SQLException {
draftServiceDAO.insertDraft(draft);
}

public void deleteDraft(DraftInterface draft, User user)
throws RuntimeException {
jdbi.useHandle(handle -> {
try {
handle.useTransaction(handler -> {
draftDAO.deleteDraftByUUIDList(List.of(draft.getUUID()));
draft.getStoredFiles().forEach(fileStorageObject -> {
try {
draftFileStorageService.deleteStoredFile(fileStorageObject, user);
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
});
} catch (Exception e) {
handle.rollback();
}
handle.commit();
});
public Set<DraftSummary> findDraftSummariesForUser(User user) {
return draftServiceDAO.findDraftSummariesForUser(user);
}

public StreamingOutput draftAsJson(DraftInterface draft) {
Gson gson = GsonUtil.buildGson();
return output -> {
output.write("{ \"document\":".getBytes());
output.write(draft.getJson().getBytes());
output.write(", \"meta\":".getBytes());
output.write(gson.toJson(draft).getBytes());
output.write("}".getBytes());
};
public DraftInterface updateDraft(DraftInterface draft, User user) throws SQLException {
return draftServiceDAO.updateDraft(draft, user);
}

public InputStream getDraftAttachmentStream(FileStorageObject targetAttachment) {
return draftFileStorageService.get(targetAttachment);
public void deleteDraft(DraftInterface draft, User user) {
draftServiceDAO.deleteDraft(draft, user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.broadinstitute.consent.http.models.UserUpdateFields;
import org.broadinstitute.consent.http.models.Vote;
import org.broadinstitute.consent.http.resources.Resource;
import org.broadinstitute.consent.http.service.dao.DraftServiceDAO;
import org.broadinstitute.consent.http.service.dao.UserServiceDAO;
import org.broadinstitute.consent.http.util.ConsentLogger;
import org.broadinstitute.consent.http.util.gson.GsonUtil;
Expand All @@ -61,14 +62,14 @@ public class UserService implements ConsentLogger {
private final UserServiceDAO userServiceDAO;
private final DaaDAO daaDAO;
private final EmailService emailService;
private final DraftService draftService;
private final DraftServiceDAO draftServiceDAO;

@Inject
public UserService(UserDAO userDAO, UserPropertyDAO userPropertyDAO, UserRoleDAO userRoleDAO,
VoteDAO voteDAO, InstitutionDAO institutionDAO, LibraryCardDAO libraryCardDAO,
AcknowledgementDAO acknowledgementDAO, FileStorageObjectDAO fileStorageObjectDAO,
SamDAO samDAO, UserServiceDAO userServiceDAO, DaaDAO daaDAO, EmailService emailService,
DraftService draftService) {
DraftServiceDAO draftServiceDAO) {
this.userDAO = userDAO;
this.userPropertyDAO = userPropertyDAO;
this.userRoleDAO = userRoleDAO;
Expand All @@ -81,7 +82,7 @@ public UserService(UserDAO userDAO, UserPropertyDAO userPropertyDAO, UserRoleDAO
this.userServiceDAO = userServiceDAO;
this.daaDAO = daaDAO;
this.emailService = emailService;
this.draftService = draftService;
this.draftServiceDAO = draftServiceDAO;
}

/**
Expand Down Expand Up @@ -268,7 +269,7 @@ public void deleteUserByEmail(String email) {
List<Integer> voteIds = votes.stream().map(Vote::getVoteId).collect(Collectors.toList());
voteDAO.removeVotesByIds(voteIds);
}
draftService.deleteDraftsByUser(user);
draftServiceDAO.deleteDraftsByUser(user);
institutionDAO.deleteAllInstitutionsByUser(userId);
userPropertyDAO.deleteAllPropertiesByUser(userId);
libraryCardDAO.deleteAllLibraryCardsByUser(userId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.broadinstitute.consent.http.service;
package org.broadinstitute.consent.http.service.dao;

import com.google.cloud.storage.BlobId;
import com.google.inject.Inject;
Expand All @@ -20,14 +20,14 @@
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.jdbi.v3.core.Jdbi;

public class DraftFileStorageService implements ConsentLogger {
public class DraftFileStorageServiceDAO implements ConsentLogger {

Jdbi jdbi;
GCSService gcsService;
FileStorageObjectDAO fileStorageObjectDAO;

@Inject
public DraftFileStorageService(Jdbi jdbi, GCSService gcsService,
public DraftFileStorageServiceDAO(Jdbi jdbi, GCSService gcsService,
FileStorageObjectDAO fileStorageObjectDAO) {
this.jdbi = jdbi;
this.gcsService = gcsService;
Expand Down Expand Up @@ -107,8 +107,4 @@ private FileStorageObject store(FormDataBodyPart file, User user, UUID draftId)
throw new RuntimeException(e);
}
}

public InputStream get(FileStorageObject fileStorageObject) {
return gcsService.getDocument(fileStorageObject.getBlobId());
}
}
Loading

0 comments on commit 81b01e2

Please sign in to comment.