Skip to content

Commit

Permalink
Merge branch 'develop' into PEPPER-947
Browse files Browse the repository at this point in the history
  • Loading branch information
pegahtah authored Jul 31, 2023
2 parents a4dc819 + 83796ab commit 8c1bc33
Show file tree
Hide file tree
Showing 68 changed files with 7,060 additions and 1,117 deletions.
2 changes: 2 additions & 0 deletions pepper-apis/ddp-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<logback.version>1.4.5</logback.version>
<sonar.sources>src/main/java</sonar.sources>
<sonar.java.binaries>target/classes</sonar.java.binaries>
<liquibase.version>4.8.0</liquibase.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -64,6 +65,7 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase.version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
Expand Down
2 changes: 1 addition & 1 deletion pepper-apis/dsm-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.3.1</version>
<version>2.4.11</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
import org.broadinstitute.dsm.route.MailingListRoute;
import org.broadinstitute.dsm.route.MedicalRecordLogRoute;
import org.broadinstitute.dsm.route.NDIRoute;
import org.broadinstitute.dsm.route.OncHistoryTemplateRoute;
import org.broadinstitute.dsm.route.OncHistoryUploadRoute;
import org.broadinstitute.dsm.route.ParticipantEventRoute;
import org.broadinstitute.dsm.route.ParticipantExitRoute;
Expand All @@ -120,6 +121,9 @@
import org.broadinstitute.dsm.route.TriggerSurveyRoute;
import org.broadinstitute.dsm.route.UserSettingRoute;
import org.broadinstitute.dsm.route.ViewFilterRoute;
import org.broadinstitute.dsm.route.admin.StudyRoleRoute;
import org.broadinstitute.dsm.route.admin.UserRoleRoute;
import org.broadinstitute.dsm.route.admin.UserRoute;
import org.broadinstitute.dsm.route.dashboard.NewDashboardRoute;
import org.broadinstitute.dsm.route.familymember.AddFamilyMemberRoute;
import org.broadinstitute.dsm.route.kit.KitFinalScanRoute;
Expand Down Expand Up @@ -583,6 +587,7 @@ protected void setupCustomRouting(@NonNull Config cfg) {
if (!cfg.getBoolean("ui.production")) {
get(apiRoot + RoutePath.CREATE_CLINICAL_KIT_ENDPOINT, new CreateClinicalDummyKitRoute(new OncHistoryDetailDaoImpl()),
new JsonTransformer());

get(apiRoot + RoutePath.CREATE_CLINICAL_KIT_ENDPOINT_WITH_PARTICIPANT, new CreateClinicalDummyKitRoute(
new OncHistoryDetailDaoImpl()), new JsonTransformer());
get(apiRoot + RoutePath.DUMMY_ENDPOINT, new CreateBSPDummyKitRoute(), new JsonTransformer());
Expand Down Expand Up @@ -666,6 +671,8 @@ protected void setupCustomRouting(@NonNull Config cfg) {

setupMiscellaneousRoutes();

setupAdminRoutes();

setupSharedRoutes(kitUtil, notificationUtil, patchUtil);

setupCohortTagRoutes();
Expand Down Expand Up @@ -868,6 +875,8 @@ private void setupMedicalRecordRoutes(@NonNull Config cfg, @NonNull Notification
post(uiRoot + RoutePath.DOWNLOAD_PARTICIPANT_LIST_ROUTE, new DownloadParticipantListRoute());

post(uiRoot + RoutePath.ONC_HISTORY_ROUTE, new OncHistoryUploadRoute(), new JsonTransformer());

get(uiRoot + RoutePath.ONC_HISTORY_TEMPLATE_ROUTE, new OncHistoryTemplateRoute());
}

private void setupMRAbstractionRoutes() {
Expand Down Expand Up @@ -912,9 +921,23 @@ private void setupMiscellaneousRoutes() {

GetParticipantDataRoute getParticipantDataRoute = new GetParticipantDataRoute();
get(uiRoot + RoutePath.GET_PARTICIPANT_DATA, getParticipantDataRoute, new JsonTransformer());
}

private void setupAdminRoutes() {
StudyRoleRoute studyRoleRoute = new StudyRoleRoute();
get(uiRoot + RoutePath.STUDY_ROLE, studyRoleRoute, new JsonTransformer());

UserRoleRoute userRoleRoute = new UserRoleRoute();
get(uiRoot + RoutePath.USER_ROLE, userRoleRoute, new JsonTransformer());
post(uiRoot + RoutePath.USER_ROLE, userRoleRoute, new JsonTransformer());
delete(uiRoot + RoutePath.USER_ROLE, userRoleRoute, new JsonTransformer());

UserRoute userRoute = new UserRoute();
post(uiRoot + RoutePath.USER, userRoute, new JsonTransformer());
delete(uiRoot + RoutePath.USER, userRoute, new JsonTransformer());
}


private void setupSomaticUploadRoutes(@NonNull Config cfg) {
SomaticResultUploadService somaticResultUploadService = SomaticResultUploadService.fromConfig(cfg);
post(uiRoot + RoutePath.SOMATIC_DOCUMENT_ROUTE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import lombok.Data;
import lombok.NonNull;
import org.broadinstitute.dsm.exception.DsmInternalError;
import org.broadinstitute.dsm.statics.DBConstants;
import org.broadinstitute.dsm.statics.QueryExtension;
import org.broadinstitute.lddp.db.SimpleResult;
Expand All @@ -27,6 +29,8 @@ public class UserSettings {
+ "WHERE user.user_id = settings.user_id AND user.is_active = 1";
private static final String SQL_INSERT_USER_SETTINGS = "INSERT INTO user_settings SET user_id = ?";

private static final String SQL_DELETE_USER_SETTINGS = "DELETE FROM user_settings WHERE user_id = ?";

private static final String USER_ID = "userId";

private int rowsOnPage;
Expand Down Expand Up @@ -104,12 +108,38 @@ public static UserSettings getUserSettings(@NonNull String email) {
return us;
}

public static void insertUserSetting(Connection conn, int userId) {
try (PreparedStatement insertKit = conn.prepareStatement(SQL_INSERT_USER_SETTINGS)) {
insertKit.setInt(1, userId);
insertKit.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException("Error inserting new user_settings ", e);
public static int createUserSettings(int userId) {
return inTransaction(conn -> insertUserSetting(conn, userId));
}

public static int insertUserSetting(Connection conn, int userId) {
int id = -1;
try (PreparedStatement stmt = conn.prepareStatement(SQL_INSERT_USER_SETTINGS, Statement.RETURN_GENERATED_KEYS)) {
stmt.setInt(1, userId);
int result = stmt.executeUpdate();
if (result != 1) {
throw new DsmInternalError("Error inserting user setting. Result count was " + result);
}
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
id = rs.getInt(1);
}
}
} catch (SQLException ex) {
throw new DsmInternalError("Error inserting user setting", ex);
}
return id;
}

public static int deleteUserSettings(int userId) {
return inTransaction(conn -> {
try (PreparedStatement stmt = conn.prepareStatement(SQL_DELETE_USER_SETTINGS)) {
stmt.setInt(1, userId);
return stmt.executeUpdate();
} catch (SQLException ex) {
String msg = String.format("Error deleting user settings: userId=%d", userId);
throw new DsmInternalError(msg, ex);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,34 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Optional;

import lombok.NonNull;
import org.broadinstitute.dsm.db.dao.Dao;
import org.broadinstitute.dsm.db.dao.util.DaoUtil;
import org.broadinstitute.dsm.db.dto.user.UserDto;
import org.broadinstitute.dsm.exception.DsmInternalError;
import org.broadinstitute.lddp.db.SimpleResult;
import spark.utils.StringUtils;

public class UserDao implements Dao<UserDto> {

public static final String USER_ID = "user_id";
public static final String NAME = "name";
public static final String EMAIL = "email";
public static final String PHONE_NUMBER = "phone_number";
private static final String SQL_INSERT_USER = "INSERT INTO access_user (name, email) VALUES (?,?)";
public static final String IS_ACTIVE = "is_active";
private static final String SQL_INSERT_USER = "INSERT INTO access_user (name, email, phone_number, is_active) VALUES (?,?,?,?)";
private static final String SQL_UPDATE_USER =
"UPDATE access_user SET name = ?, phone_number = ?, is_active = ? WHERE user_id = ?";
private static final String SQL_DELETE_USER_BY_ID = "DELETE FROM access_user WHERE user_id = ?";
private static final String SQL_SELECT_USER_BY_EMAIL =
"SELECT user.user_id, user.name, user.email, user.phone_number FROM access_user user WHERE user.email = ?";
"SELECT user.user_id, user.name, user.email, user.phone_number, user.is_active FROM access_user user "
+ "WHERE user.email = ?";
private static final String SQL_SELECT_USER_BY_ID =
"SELECT user.user_id, user.name, user.email, user.phone_number FROM access_user user WHERE user.user_id = ?";
"SELECT user.user_id, user.name, user.email, user.phone_number, user.is_active FROM access_user user "
+ "WHERE user.user_id = ?";

public Optional<UserDto> getUserByEmail(@NonNull String email) {
SimpleResult results = inTransaction((conn) -> {
Expand All @@ -35,7 +44,8 @@ public Optional<UserDto> getUserByEmail(@NonNull String email) {
dbVals.resultValue = new UserDto(rs.getInt(USER_ID),
rs.getString(NAME),
rs.getString(EMAIL),
rs.getString(PHONE_NUMBER));
rs.getString(PHONE_NUMBER),
rs.getInt(IS_ACTIVE));
}
}
} catch (SQLException ex) {
Expand All @@ -45,7 +55,7 @@ public Optional<UserDto> getUserByEmail(@NonNull String email) {
});

if (results.resultException != null) {
throw new RuntimeException("Error getting list of realms ", results.resultException);
throw new DsmInternalError("Error getting user by email " + email, results.resultException);
}
return Optional.ofNullable((UserDto) results.resultValue);
}
Expand All @@ -61,7 +71,8 @@ public Optional<UserDto> get(long userId) {
dbVals.resultValue = new UserDto(rs.getInt(USER_ID),
rs.getString(NAME),
rs.getString(EMAIL),
rs.getString(PHONE_NUMBER));
rs.getString(PHONE_NUMBER),
rs.getInt(IS_ACTIVE));
}
}
} catch (SQLException ex) {
Expand All @@ -71,52 +82,63 @@ public Optional<UserDto> get(long userId) {
});

if (results.resultException != null) {
throw new RuntimeException("Error getting list of realms ", results.resultException);
throw new DsmInternalError("Error getting user by id " + userId, results.resultException);
}
return Optional.ofNullable((UserDto) results.resultValue);
}

@Override
public int create(UserDto userDto) {
SimpleResult results = inTransaction((conn) -> {
SimpleResult execResult = new SimpleResult();
try (PreparedStatement stmt = conn.prepareStatement(SQL_INSERT_USER, PreparedStatement.RETURN_GENERATED_KEYS)) {
stmt.setString(1, userDto.getName().orElse(""));
stmt.setString(2, userDto.getEmail().orElse(""));
String email = userDto.getEmailOrThrow();
if (StringUtils.isBlank(email)) {
throw new DsmInternalError("Error inserting user: email is blank");
}
return inTransaction(conn -> {
try (PreparedStatement stmt = conn.prepareStatement(SQL_INSERT_USER, Statement.RETURN_GENERATED_KEYS)) {
stmt.setString(1, userDto.getName().orElse(null));
stmt.setString(2, email);
stmt.setString(3, userDto.getPhoneNumber().orElse(null));
stmt.setInt(4, userDto.getIsActive().orElse(1));
stmt.executeUpdate();
try (ResultSet rs = stmt.getGeneratedKeys()) {
if (rs.next()) {
execResult.resultValue = rs.getInt(1);
if (!rs.next()) {
throw new DsmInternalError("Error inserting user " + email);
}
return rs.getInt(1);
}
} catch (SQLException ex) {
execResult.resultException = ex;
throw new DsmInternalError("Error inserting user " + email, ex);
}
return execResult;
});
if (results.resultException != null) {
throw new RuntimeException("Error inserting user with "
+ userDto.getEmail(), results.resultException);
}
return (int) results.resultValue;
}

@Override
public int delete(int id) {
SimpleResult results = inTransaction((conn) -> {
SimpleResult execResult = new SimpleResult();
try (PreparedStatement stmt = conn.prepareStatement(SQL_DELETE_USER_BY_ID)) {
stmt.setInt(1, id);
execResult.resultValue = stmt.executeUpdate();
public static void update(int userId, UserDto userDto) {
String email = userDto.getEmailOrThrow();
String errorMsg = "Error updating user " + email;
int res = inTransaction(conn -> {
try (PreparedStatement stmt = conn.prepareStatement(SQL_UPDATE_USER)) {
stmt.setString(1, userDto.getName().orElse(null));
stmt.setString(2, userDto.getPhoneNumber().orElse(null));
stmt.setInt(3, userDto.getIsActive().orElse(1));
stmt.setInt(4, userId);
int result = stmt.executeUpdate();
if (result != 1) {
throw new DsmInternalError(errorMsg + " Result count was " + result);
}
return result;
} catch (SQLException ex) {
execResult.resultException = ex;
throw new DsmInternalError(errorMsg, ex);
}
return execResult;
});
if (results.resultException != null) {
throw new RuntimeException("Error deleting user with "
+ id, results.resultException);
}

@Override
public int delete(int id) {
SimpleResult simpleResult = DaoUtil.deleteById(id, SQL_DELETE_USER_BY_ID);
if (simpleResult.resultException != null) {
throw new DsmInternalError("Error deleting user with ID: " + id,
simpleResult.resultException);
}
return (int) results.resultValue;
return (int) simpleResult.resultValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@

import java.util.Optional;

import lombok.AllArgsConstructor;
import lombok.Setter;
import org.broadinstitute.dsm.exception.DsmInternalError;

@Setter
@AllArgsConstructor
public class UserDto {

private int id;
private String name;
private String email;
private String phoneNumber;
private Integer isActive;

public UserDto(int id, String name, String email, String phoneNumber) {
this.id = id;
public UserDto(String name, String email, String phoneNumber) {
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
}

public UserDto() {

}

public int getId() {
Expand All @@ -35,7 +37,20 @@ public Optional<String> getEmail() {
return Optional.ofNullable(email);
}

// TODO: getEmail should always throw on a missing email since it is not nullable
// but there are a lot of callers. Feel free to chase them all down and rename this method -DC
public String getEmailOrThrow() {
return getEmail().orElseThrow(() -> new DsmInternalError("User email cannot be null"));
}

public Optional<String> getPhoneNumber() {
return Optional.ofNullable(phoneNumber);
}
public Optional<Integer> getIsActive() {
return Optional.ofNullable(isActive);
}

public boolean isActive() {
return getIsActive().orElse(0) == 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,27 @@ public Optional<String> findMissingHeaderIfAny(List<String> extractedHeaders) {

List<T> transformRecordsToList(String[] records) {
return Arrays.stream(records)
.filter(this::filterRecord)
.map(this::transformRecordToMap)
.map(this::transformMapToObject)
.collect(Collectors.toList());
}

/**
* Return false if the record has no content (but may have delimiters)
*/
boolean filterRecord(String record) {
String regex = String.format("[%s]", regexSeparator);
return !cleanRecord(record).replaceAll(regex, "").isEmpty();
}

String cleanRecord(String record) {
return record.replaceAll("[\n\r]$", "");
}

Map<String, String> transformRecordToMap(String record) {
// split but keep trailing delimiters
List<String> records = Arrays.asList(record.replaceAll("[\n\r]$", "").split(regexSeparator, -1));
List<String> records = Arrays.asList(cleanRecord(record).split(regexSeparator, -1));
int colDiff = actualHeaders.size() - records.size();
if (colDiff > 0) {
String row = String.join(", ", records);
Expand Down
Loading

0 comments on commit 8c1bc33

Please sign in to comment.