Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_CREATED_BY;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_CREATED_ON;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_ETAG;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_MODIFIED_BY;
Expand All @@ -16,12 +17,12 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.sagebionetworks.repo.model.dbo.FieldColumn;
import org.sagebionetworks.repo.model.dbo.MigratableDatabaseObject;
import org.sagebionetworks.repo.model.dbo.TableMapping;
import org.sagebionetworks.repo.model.dbo.migration.BasicMigratableTableTranslation;
import org.sagebionetworks.repo.model.dbo.migration.MigratableTableTranslation;
import org.sagebionetworks.repo.model.migration.MigrationType;

Expand All @@ -36,7 +37,8 @@ public class DBORequest implements MigratableDatabaseObject<DBORequest, DBOReque
new FieldColumn("modifiedBy", COL_DATA_ACCESS_REQUEST_MODIFIED_BY),
new FieldColumn("modifiedOn", COL_DATA_ACCESS_REQUEST_MODIFIED_ON),
new FieldColumn("etag", COL_DATA_ACCESS_REQUEST_ETAG).withIsEtag(true),
new FieldColumn("requestSerialized", COL_DATA_ACCESS_REQUEST_REQUEST_SERIALIZED).withHasFileHandleRef(true)
new FieldColumn("requestSerialized", COL_DATA_ACCESS_REQUEST_REQUEST_SERIALIZED).withHasFileHandleRef(true),
new FieldColumn("eDucEnvelopeId", COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID)
};

private Long id;
Expand All @@ -48,6 +50,7 @@ public class DBORequest implements MigratableDatabaseObject<DBORequest, DBOReque
private Long modifiedOn;
private String etag;
private byte[] requestSerialized;
private String eDucEnvelopeId;

@Override
public String toString() {
Expand Down Expand Up @@ -199,6 +202,14 @@ public void setRequestSerialized(byte[] requestSerialized) {
this.requestSerialized = requestSerialized;
}

public String getEDucEnvelopeId() {
return eDucEnvelopeId;
}

public void setEDucEnvelopeId(String eDucEnvelopeId) {
this.eDucEnvelopeId = eDucEnvelopeId;
}

@Override
public TableMapping<DBORequest> getTableMapping() {
return new TableMapping<DBORequest>(){
Expand All @@ -216,6 +227,7 @@ public DBORequest mapRow(ResultSet rs, int rowNum) throws SQLException {
dbo.setEtag(rs.getString(COL_DATA_ACCESS_REQUEST_ETAG));
Blob blob = rs.getBlob(COL_DATA_ACCESS_REQUEST_REQUEST_SERIALIZED);
dbo.setRequestSerialized(blob.getBytes(1, (int) blob.length()));
dbo.setEDucEnvelopeId(rs.getString(COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID));
return dbo;
}

Expand Down Expand Up @@ -249,7 +261,27 @@ public MigrationType getMigratableTableType() {

@Override
public MigratableTableTranslation<DBORequest, DBORequest> getTranslator() {
return new BasicMigratableTableTranslation<DBORequest>();
return new MigratableTableTranslation<DBORequest, DBORequest>() {
@Override
public DBORequest createDatabaseObjectFromBackup(DBORequest backup) {
if (backup.getEDucEnvelopeId() == null && backup.getRequestSerialized() != null) {
try {
var dto = RequestUtils.readSerializedField(backup.getRequestSerialized());
if (dto.getEDucSignatureEnvelopeId() != null) {
backup.setEDucEnvelopeId(dto.getEDucSignatureEnvelopeId());
}
} catch (Exception e) {
// If deserialization fails during migration, skip populating the column
}
}
return backup;
}

@Override
public DBORequest createBackupFromDatabaseObject(DBORequest dbo) {
return dbo;
}
};
}

@Override
Expand All @@ -264,7 +296,9 @@ public Class<? extends DBORequest> getDatabaseObjectClass() {

@Override
public List<MigratableDatabaseObject<?, ?>> getSecondaryTypes() {
return null;
List<MigratableDatabaseObject<?, ?>> list = new LinkedList<>();
list.add(new DBORequestUser());
return list;
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
package org.sagebionetworks.repo.model.dbo.dao.dataaccess;

import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_ACCESS_REQUIREMENT_NAME;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_CREATED_BY;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_MODIFIED_ON;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_USER_REQUEST_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_REQUEST_USER_USER_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_DATA_ACCESS_REQUEST_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_STATUS_CREATED_ON;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_STATUS_MODIFIED_ON;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_STATUS_STATE;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.COL_DATA_ACCESS_SUBMISSION_STATUS_SUBMISSION_ID;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.TABLE_ACCESS_REQUIREMENT;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.TABLE_DATA_ACCESS_REQUEST;

import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.TABLE_DATA_ACCESS_REQUEST_USER;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.TABLE_DATA_ACCESS_SUBMISSION;
import static org.sagebionetworks.repo.model.query.jdo.SqlConstants.TABLE_DATA_ACCESS_SUBMISSION_STATUS;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.UUID;

import org.sagebionetworks.ids.IdGenerator;
import org.sagebionetworks.ids.IdType;
import org.sagebionetworks.repo.model.dataaccess.AccessType;
import org.sagebionetworks.repo.model.dataaccess.AccessorChange;
import org.sagebionetworks.repo.model.dataaccess.PrincipalInvestigator;
import org.sagebionetworks.repo.model.dataaccess.Request;
import org.sagebionetworks.repo.model.dataaccess.RequestInterface;
import org.sagebionetworks.repo.model.dbo.DBOBasicDao;
Expand All @@ -22,7 +46,7 @@
import org.springframework.stereotype.Repository;

@Repository
public class DBORequestDAOImpl implements RequestDAO{
public class DBORequestDAOImpl implements RequestDAO {

public static final String DATA_ACCESS_REQUEST_DOES_NOT_EXIST = "Data access request: '%s' does not exist";

Expand All @@ -35,26 +59,62 @@ public class DBORequestDAOImpl implements RequestDAO{
@Autowired
private IdGenerator idGenerator;

public static final String SQL_DELETE = "DELETE FROM "+TABLE_DATA_ACCESS_REQUEST
+ " WHERE "+COL_DATA_ACCESS_REQUEST_ID+" = ?";
public static final String SQL_DELETE = "DELETE FROM " + TABLE_DATA_ACCESS_REQUEST
+ " WHERE " + COL_DATA_ACCESS_REQUEST_ID + " = ?";

public static final String SQL_GET = "SELECT *"
+ " FROM "+TABLE_DATA_ACCESS_REQUEST
+ " WHERE "+COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID+" = ?"
+ " AND "+COL_DATA_ACCESS_REQUEST_CREATED_BY+" = ?";
+ " FROM " + TABLE_DATA_ACCESS_REQUEST
+ " WHERE " + COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID + " = ?"
+ " AND " + COL_DATA_ACCESS_REQUEST_CREATED_BY + " = ?";

public static final String SQL_GET_BY_ID = "SELECT *"
+ " FROM "+TABLE_DATA_ACCESS_REQUEST
+ " WHERE "+COL_DATA_ACCESS_REQUEST_ID+" = ?";

public static final String SQL_GET_AR_ID_BY_ID = "SELECT " + COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID
+ " FROM "+TABLE_DATA_ACCESS_REQUEST
+ " WHERE "+COL_DATA_ACCESS_REQUEST_ID+" = ?";
+ " FROM " + TABLE_DATA_ACCESS_REQUEST
+ " WHERE " + COL_DATA_ACCESS_REQUEST_ID + " = ?";

public static final String SQL_GET_FOR_UPDATE = SQL_GET_BY_ID+" FOR UPDATE";
public static final String SQL_GET_AR_ID_BY_ID = "SELECT " + COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID
+ " FROM " + TABLE_DATA_ACCESS_REQUEST
+ " WHERE " + COL_DATA_ACCESS_REQUEST_ID + " = ?";

public static final String SQL_GET_FOR_UPDATE = SQL_GET_BY_ID + " FOR UPDATE";

private static final String SQL_DELETE_REQUEST_USERS = "DELETE FROM " + TABLE_DATA_ACCESS_REQUEST_USER
+ " WHERE " + COL_DATA_ACCESS_REQUEST_USER_REQUEST_ID + " = ?";

private static final String SQL_GET_USER_REQUESTS =
"SELECT r." + COL_DATA_ACCESS_REQUEST_ID + " AS REQUEST_ID"
+ ", r." + COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID + " AS ACCESS_REQUIREMENT_ID"
+ ", ar." + COL_ACCESS_REQUIREMENT_NAME + " AS ACCESS_REQUIREMENT_NAME"
+ ", ss." + COL_DATA_ACCESS_SUBMISSION_STATUS_STATE + " AS SUBMISSION_STATUS"
+ ", r." + COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID + " IS NOT NULL AS IS_EDUC"
+ ", r." + COL_DATA_ACCESS_REQUEST_EDUC_ENVELOPE_ID + " AS ENVELOPE_ID"
+ ", ss." + COL_DATA_ACCESS_SUBMISSION_STATUS_CREATED_ON + " AS SUBMITTED_ON"
+ ", ss." + COL_DATA_ACCESS_SUBMISSION_STATUS_MODIFIED_ON + " AS MODIFIED_ON"
+ " FROM " + TABLE_DATA_ACCESS_REQUEST + " r"
+ " JOIN " + TABLE_DATA_ACCESS_REQUEST_USER + " ru ON r." + COL_DATA_ACCESS_REQUEST_ID + " = ru." + COL_DATA_ACCESS_REQUEST_USER_REQUEST_ID
+ " JOIN " + TABLE_ACCESS_REQUIREMENT + " ar ON r." + COL_DATA_ACCESS_REQUEST_ACCESS_REQUIREMENT_ID + " = ar.ID"
+ " LEFT JOIN " + TABLE_DATA_ACCESS_SUBMISSION + " s ON s." + COL_DATA_ACCESS_SUBMISSION_DATA_ACCESS_REQUEST_ID + " = r." + COL_DATA_ACCESS_REQUEST_ID
+ " LEFT JOIN " + TABLE_DATA_ACCESS_SUBMISSION_STATUS + " ss ON ss." + COL_DATA_ACCESS_SUBMISSION_STATUS_SUBMISSION_ID + " = s." + COL_DATA_ACCESS_SUBMISSION_ID
+ " WHERE ru." + COL_DATA_ACCESS_REQUEST_USER_USER_ID + " = ?"
+ " ORDER BY r." + COL_DATA_ACCESS_REQUEST_MODIFIED_ON + " DESC"
+ " LIMIT ? OFFSET ?";

private static final RowMapper<DBORequest> MAPPER = new DBORequest().getTableMapping();

private static final RowMapper<RequestUserInfo> USER_REQUEST_MAPPER = (ResultSet rs, int rowNum) -> {
RequestUserInfo info = new RequestUserInfo();
info.setRequestId(String.valueOf(rs.getLong("REQUEST_ID")));
info.setAccessRequirementId(String.valueOf(rs.getLong("ACCESS_REQUIREMENT_ID")));
info.setAccessRequirementName(rs.getString("ACCESS_REQUIREMENT_NAME"));
info.setSubmissionStatus(rs.getString("SUBMISSION_STATUS"));
info.setIsEDuc(rs.getBoolean("IS_EDUC"));
info.setEnvelopeId(rs.getString("ENVELOPE_ID"));
long submittedOn = rs.getLong("SUBMITTED_ON");
info.setSubmittedOn(rs.wasNull() ? null : new Date(submittedOn));
long modifiedOn = rs.getLong("MODIFIED_ON");
info.setModifiedOn(rs.wasNull() ? null : new Date(modifiedOn));
return info;
};

@WriteTransaction
@Override
public Request create(Request toCreate) {
Expand All @@ -63,6 +123,7 @@ public Request create(Request toCreate) {
DBORequest dbo = new DBORequest();
RequestUtils.copyDtoToDbo(toCreate, dbo);
basicDao.createNew(dbo);
populateRequestUsers(toCreate);
return (Request) getUserOwnCurrentRequest(toCreate.getAccessRequirementId(), toCreate.getCreatedBy());
}

Expand All @@ -71,8 +132,7 @@ public RequestInterface getUserOwnCurrentRequest(String accessRequirementId, Str
throws NotFoundException {
try {
DBORequest dbo = jdbcTemplate.queryForObject(SQL_GET, MAPPER, accessRequirementId, userId);
RequestInterface dto = RequestUtils.copyDboToDto(dbo);
return dto;
return RequestUtils.copyDboToDto(dbo);
} catch (EmptyResultDataAccessException e) {
throw new NotFoundException(String.format("Data access request does not exist for access requirement: '%s' and user id: '%s'", accessRequirementId, userId));
}
Expand All @@ -85,6 +145,7 @@ public RequestInterface update(RequestInterface toUpdate) throws NotFoundExcepti
RequestUtils.copyDtoToDbo(toUpdate, dbo);
dbo.setEtag(UUID.randomUUID().toString());
basicDao.update(dbo);
populateRequestUsers(toUpdate);
return getUserOwnCurrentRequest(toUpdate.getAccessRequirementId(), toUpdate.getCreatedBy());
}

Expand All @@ -98,8 +159,7 @@ public void delete(String id) {
public RequestInterface getForUpdate(String id) {
try {
DBORequest dbo = jdbcTemplate.queryForObject(SQL_GET_FOR_UPDATE, MAPPER, id);
RequestInterface dto = RequestUtils.copyDboToDto(dbo);
return dto;
return RequestUtils.copyDboToDto(dbo);
} catch (EmptyResultDataAccessException e) {
throw new NotFoundException(String.format(DATA_ACCESS_REQUEST_DOES_NOT_EXIST, id));
}
Expand All @@ -109,13 +169,12 @@ public RequestInterface getForUpdate(String id) {
public RequestInterface get(String id) {
try {
DBORequest dbo = jdbcTemplate.queryForObject(SQL_GET_BY_ID, MAPPER, id);
RequestInterface dto = RequestUtils.copyDboToDto(dbo);
return dto;
return RequestUtils.copyDboToDto(dbo);
} catch (EmptyResultDataAccessException e) {
throw new NotFoundException(String.format(DATA_ACCESS_REQUEST_DOES_NOT_EXIST, id));
}
}

@Override
public String getAccessRequirementId(String requestId) {
try {
Expand All @@ -125,9 +184,54 @@ public String getAccessRequirementId(String requestId) {
}
}

@Override
public List<RequestUserInfo> getUserRequests(Long userId, long limit, long offset) {
return jdbcTemplate.query(SQL_GET_USER_REQUESTS, USER_REQUEST_MAPPER, userId, limit, offset);
}

@Override
public void truncateAll() {
jdbcTemplate.update("DELETE FROM " + TABLE_DATA_ACCESS_REQUEST);
}

private void populateRequestUsers(RequestInterface request) {
Long requestId = Long.parseLong(request.getId());
jdbcTemplate.update(SQL_DELETE_REQUEST_USERS, requestId);

List<DBORequestUser> users = buildRequestUsers(request);
if (!users.isEmpty()) {
basicDao.createBatch(users);
}
}

List<DBORequestUser> buildRequestUsers(RequestInterface request) {
Long requestId = Long.parseLong(request.getId());
LinkedHashSet<Long> userIds = new LinkedHashSet<>();

userIds.add(Long.parseLong(request.getCreatedBy()));

PrincipalInvestigator pi = request.getPrincipalInvestigator();
if (pi != null && pi.getUserId() != null) {
userIds.add(Long.parseLong(pi.getUserId()));
}

List<AccessorChange> accessorChanges = request.getAccessorChanges();
if (accessorChanges != null) {
for (AccessorChange change : accessorChanges) {
if (AccessType.GAIN_ACCESS.equals(change.getType())
|| AccessType.RENEW_ACCESS.equals(change.getType())) {
userIds.add(Long.parseLong(change.getUserId()));
}
}
}

List<DBORequestUser> result = new ArrayList<>(userIds.size());
for (Long userId : userIds) {
DBORequestUser dbo = new DBORequestUser();
dbo.setRequestId(requestId);
dbo.setUserId(userId);
result.add(dbo);
}
return result;
}
}
Loading
Loading