Skip to content

Commit

Permalink
Add DBTests
Browse files Browse the repository at this point in the history
  • Loading branch information
Mythicaeda committed Sep 21, 2023
1 parent 0da269d commit 100261b
Showing 1 changed file with 285 additions and 12 deletions.
297 changes: 285 additions & 12 deletions db-tests/src/test/java/gov/nasa/jpl/aerie/database/PermissionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class PermissionsTest {
private static final File initSqlScriptFile = new File("../merlin-server/sql/merlin/init.sql");
private static final String testRole = "testRole";
private enum FunctionPermissionKey {
apply_preset,
begin_merge,
Expand Down Expand Up @@ -71,22 +72,12 @@ void beforeEach() throws SQLException {
void afterEach() throws SQLException {
helper.clearTable("uploaded_file");
helper.clearTable("mission_model");
helper.clearTable("activity_type");
helper.clearTable("plan");
helper.clearTable("plan_collaborators");
helper.clearTable("activity_directive");
helper.clearTable("simulation_template");
helper.clearTable("simulation");
helper.clearTable("dataset");
helper.clearTable("plan_dataset");
helper.clearTable("simulation_dataset");
helper.clearTable("plan_snapshot");
helper.clearTable("plan_latest_snapshot");
helper.clearTable("plan_snapshot_activities");
helper.clearTable("plan_snapshot_parent");
helper.clearTable("merge_request");
helper.clearTable("merge_staging_area");
helper.clearTable("conflicting_activities");
helper.clearTable("anchor_validation_status");
helper.clearTable("plan_collaborators");
}

@BeforeAll
Expand All @@ -99,6 +90,7 @@ void beforeAll() throws SQLException, IOException, InterruptedException {
helper.startDatabase();
connection = helper.connection();
merlinHelper = new MerlinDatabaseTestHelper(connection);
insertUserRole(testRole);
}

@AfterAll
Expand Down Expand Up @@ -161,6 +153,54 @@ private void checkMergePermissions(
""".formatted(permission, planIdReceiving, planIdSupplying, username));
}
}

private void insertUserRole(String role) throws SQLException {
try(final var statement = connection.createStatement()){
statement.execute(
//language=sql
"""
insert into metadata.user_roles(role, description)
values ('%s', 'A role created during DBTests');
""".formatted(role));
}
}

private void updateUserRolePermissions(
String role,
String actionPermissionsJson,
String functionPermissionsJson)
throws SQLException {
try(final var statement = connection.createStatement()){
if(actionPermissionsJson == null){
statement.execute(
//language=sql
"""
update metadata.user_role_permission
set function_permissions = '%s'::jsonb
where role = '%s';
""".formatted(functionPermissionsJson, role));
} else if (functionPermissionsJson == null) {
statement.execute(
//language=sql
"""
update metadata.user_role_permission
set action_permissions = '%s'::jsonb
where role = '%s';
""".formatted(actionPermissionsJson, role));
}
else {
statement.execute(
//language=sql
"""
update metadata.user_role_permission
set action_permissions = '%s'::jsonb,
function_permissions = '%s'::jsonb
where role = '%s';
""".formatted(actionPermissionsJson, functionPermissionsJson, role));
}

}
}
//endregion

@Test
Expand Down Expand Up @@ -747,4 +787,237 @@ void testPlanOwnerCollaboratorTarget() throws SQLException {
}
}
}

@Nested
class UserRolePermissionsValidation{
private final String invalidJsonTextErrCode = "22032";
@Test
void emptyIsValid() {
// Action
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, "{}", null));
// Function
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, null, "{}"));
// Both
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, "{}", "{}"));
}

@Test
void nonsenseKeys() throws SQLException {
// Nonsense Values for Keys are caught
final String actionPermissions = "{\"fake_action_key\": \"NO_CHECK\"}";
final String functionPermissions = "{\"fake_function_key\": \"NO_CHECK\"}";
// Action
final String actionExceptionMsg =
"""
ERROR: invalid keys in supplied row
Detail: The following action keys are not valid: fake_action_key
Hint:
""".trim();
final var actionException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, null));
if( !actionException.getMessage().contains(actionExceptionMsg)
|| !actionException.getSQLState().equals(invalidJsonTextErrCode)){
throw actionException;
}

// Function
final String fnExceptionMsg =
"""
ERROR: invalid keys in supplied row
Detail: The following function keys are not valid: fake_function_key
Hint:
""".trim();
final var fnException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, null, functionPermissions));
if(!fnException.getMessage().contains(fnExceptionMsg)
|| !fnException.getSQLState().equals(invalidJsonTextErrCode)){
throw fnException;
}
// Both
final String bothExceptionMsg =
"""
ERROR: invalid keys in supplied row
Detail: The following action keys are not valid: fake_action_key
The following function keys are not valid: fake_function_key
Hint:
""".trim();
final var bothException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, functionPermissions));
if(!bothException.getMessage().contains(bothExceptionMsg)
|| !bothException.getSQLState().equals(invalidJsonTextErrCode)){
throw bothException;
}
}

@Test
void nonsensePermissions() throws SQLException {
// Nonsense Values for Permissions are caught
final String actionPermissions = "{\"simulate\": \"NONSENSE_PERMISSION\"}";
final String functionPermissions = "{\"begin_merge\": \"NONSENSE_PERMISSION\"}";
// Action
final String actionExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following action keys have invalid permissions: {simulate: NONSENSE_PERMISSION}
Hint:
""".trim();
final var actionException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, null));
if( !actionException.getMessage().contains(actionExceptionMsg)
|| !actionException.getSQLState().equals(invalidJsonTextErrCode)){
throw actionException;
}

// Function
final String fnExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following function keys have invalid permissions: {begin_merge: NONSENSE_PERMISSION}
Hint:
""".trim();
final var fnException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, null, functionPermissions));
if(!fnException.getMessage().contains(fnExceptionMsg)
|| !fnException.getSQLState().equals(invalidJsonTextErrCode)){
throw fnException;
}
// Both
final String bothExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following action keys have invalid permissions: {simulate: NONSENSE_PERMISSION}
The following function keys have invalid permissions: {begin_merge: NONSENSE_PERMISSION}
Hint:
""".trim();
final var bothException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, functionPermissions));
if(!bothException.getMessage().contains(bothExceptionMsg)
|| !bothException.getSQLState().equals(invalidJsonTextErrCode)){
throw bothException;
}
}

@Test
void invalidPermissions() throws SQLException {
// Improperly applied Plan Merge Permissions are caught
final String actionPermissions = "{\"simulate\": \"PLAN_OWNER_SOURCE\"}";
final String functionPermissions = "{\"apply_preset\": \"PLAN_OWNER_TARGET\"}";
// Action
final String actionExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following action keys may not take plan merge permissions: {simulate: PLAN_OWNER_SOURCE}
Hint:
""".trim();
final var actionException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, null));
if( !actionException.getMessage().contains(actionExceptionMsg)
|| !actionException.getSQLState().equals(invalidJsonTextErrCode)){
throw actionException;
}

// Function
final String fnExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following function keys may not take plan merge permissions: {apply_preset: PLAN_OWNER_TARGET}
Hint:
""".trim();
final var fnException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, null, functionPermissions));
if(!fnException.getMessage().contains(fnExceptionMsg)
|| !fnException.getSQLState().equals(invalidJsonTextErrCode)){
throw fnException;
}
// Both
final String bothExceptionMsg =
"""
ERROR: invalid permissions in supplied row
Detail: The following action keys may not take plan merge permissions: {simulate: PLAN_OWNER_SOURCE}
The following function keys may not take plan merge permissions: {apply_preset: PLAN_OWNER_TARGET}
Hint:
""".trim();
final var bothException = assertThrows(SQLException.class,
() -> updateUserRolePermissions(testRole, actionPermissions, functionPermissions));
if(!bothException.getMessage().contains(bothExceptionMsg)
|| !bothException.getSQLState().equals(invalidJsonTextErrCode)){
throw bothException;
}
}

@Test
void incompleteIsValid() {
// Updates Viewer Role Permissions, which is an incomplete set
final String actionPermissions = """
{
"sequence_seq_json_bulk": "NO_CHECK",
"resource_samples": "NO_CHECK"
}
""";
final String functionPermissions = """
{
"get_conflicting_activities": "NO_CHECK",
"get_non_conflicting_activities": "NO_CHECK",
"get_plan_history": "NO_CHECK"
}
""";
// Action
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, actionPermissions, null));
// Function
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, null, functionPermissions));
// Both
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, actionPermissions, functionPermissions));
}

@Test
void completeIsValid() {
// Uses User Role Permissions to check that a complete set is valid
// and that plan merge permissions on plan merge functions is valid
final String actionPermissions = """
{
"check_constraints": "PLAN_OWNER_COLLABORATOR",
"create_expansion_rule": "NO_CHECK",
"create_expansion_set": "NO_CHECK",
"expand_all_activities": "NO_CHECK",
"insert_ext_dataset": "PLAN_OWNER",
"resource_samples": "NO_CHECK",
"schedule":"PLAN_OWNER_COLLABORATOR",
"sequence_seq_json_bulk": "NO_CHECK",
"simulate":"PLAN_OWNER_COLLABORATOR"
}
""";
final String functionPermissions = """
{
"apply_preset": "PLAN_OWNER_COLLABORATOR",
"begin_merge": "PLAN_OWNER_TARGET",
"branch_plan": "NO_CHECK",
"cancel_merge": "PLAN_OWNER_TARGET",
"commit_merge": "PLAN_OWNER_TARGET",
"create_merge_rq": "PLAN_OWNER_SOURCE",
"create_snapshot": "PLAN_OWNER_COLLABORATOR",
"delete_activity_reanchor": "PLAN_OWNER_COLLABORATOR",
"delete_activity_reanchor_bulk": "PLAN_OWNER_COLLABORATOR",
"delete_activity_reanchor_plan": "PLAN_OWNER_COLLABORATOR",
"delete_activity_reanchor_plan_bulk": "PLAN_OWNER_COLLABORATOR",
"delete_activity_subtree": "PLAN_OWNER_COLLABORATOR",
"delete_activity_subtree_bulk": "PLAN_OWNER_COLLABORATOR",
"deny_merge": "PLAN_OWNER_TARGET",
"get_conflicting_activities": "NO_CHECK",
"get_non_conflicting_activities": "NO_CHECK",
"get_plan_history": "NO_CHECK",
"restore_activity_changelog": "PLAN_OWNER_COLLABORATOR",
"restore_snapshot": "PLAN_OWNER_COLLABORATOR",
"set_resolution": "PLAN_OWNER_TARGET",
"set_resolution_bulk": "PLAN_OWNER_TARGET",
"withdraw_merge_rq": "PLAN_OWNER_SOURCE"
}
""";
// Action
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, actionPermissions, null));
// Function
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, null, functionPermissions));
// Both
assertDoesNotThrow(() -> updateUserRolePermissions(testRole, actionPermissions, functionPermissions));
}
}
}

0 comments on commit 100261b

Please sign in to comment.