refactor RbacGrantControllerAcceptanceTest introducing fixture classes for better readability

This commit is contained in:
Michael Hoennig 2022-08-18 13:47:22 +02:00
parent 8a62d9802e
commit eebe2d40a6

View File

@ -2,6 +2,7 @@ package net.hostsharing.hsadminng.rbac.rbacgrant;
import io.restassured.RestAssured; import io.restassured.RestAssured;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import net.hostsharing.hsadminng.Accepts; import net.hostsharing.hsadminng.Accepts;
import net.hostsharing.hsadminng.HsadminNgApplication; import net.hostsharing.hsadminng.HsadminNgApplication;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
@ -28,8 +29,8 @@ import static org.assertj.core.api.Assumptions.assumeThat;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
@SpringBootTest( @SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { HsadminNgApplication.class, JpaAttempt.class } classes = { HsadminNgApplication.class, JpaAttempt.class }
) )
@Accepts({ "GRT:S(Schema)" }) @Accepts({ "GRT:S(Schema)" })
@Transactional(readOnly = true, propagation = Propagation.NEVER) @Transactional(readOnly = true, propagation = Propagation.NEVER)
@ -64,40 +65,23 @@ class RbacGrantControllerAcceptanceTest {
void packageAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() { void packageAdmin_canGrantOwnPackageAdminRole_toArbitraryUser() {
// given // given
final var givenNewUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com"; final var givenNewUser = createRBacUser();
final var givenCurrentUserPackageAdmin = "aaa00@aaa.example.com"; final var givenRoleToGrant = "package#aaa00.admin";
final var givenAssumedRole = "package#aaa00.admin"; final var givenCurrentUserAsPackageAdmin = new Subject("aaa00@aaa.example.com", givenRoleToGrant);
final var givenOwnPackageAdminRole = "package#aaa00.admin"; final var givenOwnPackageAdminRole =
findRbacRoleByName(givenCurrentUserAsPackageAdmin.assumedRole);
// when // when
RestAssured // @formatter:off givenCurrentUserAsPackageAdmin
.given() .grantsRole(givenOwnPackageAdminRole).assumed()
.header("current-user", givenCurrentUserPackageAdmin) .toUser(givenNewUser);
.header("assumed-roles", givenAssumedRole)
.contentType(ContentType.JSON)
.body("""
{
"assumed": true,
"grantedRoleUuid": "%s",
"granteeUserUuid": "%s"
}
""".formatted(
findRbacRoleByName(givenOwnPackageAdminRole).getUuid().toString(),
createRBacUser(givenNewUserName).getUuid().toString())
)
.port(port)
.when()
.post("http://localhost/api/rbac-grants")
.then().assertThat()
.statusCode(201);
// @formatter:on
// then // then
assertThat(findAllGrantsOfUser(givenCurrentUserPackageAdmin)) assertThat(findAllGrantsOf(givenCurrentUserAsPackageAdmin))
.extracting(RbacGrantEntity::toDisplay) .extracting(RbacGrantEntity::toDisplay)
.contains("{ grant assumed role " + givenOwnPackageAdminRole + .contains("{ grant assumed role " + givenOwnPackageAdminRole.getRoleName() +
" to user " + givenNewUserName + " to user " + givenNewUser.getName() +
" by role " + givenAssumedRole + " }"); " by role " + givenRoleToGrant + " }");
} }
@Test @Test
@ -105,40 +89,24 @@ class RbacGrantControllerAcceptanceTest {
void packageAdmin_canNotGrantAlienPackageAdminRole_toArbitraryUser() { void packageAdmin_canNotGrantAlienPackageAdminRole_toArbitraryUser() {
// given // given
final var givenNewUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com"; final var givenNewUser = createRBacUser();
final var givenCurrentUserPackageAdmin = "aaa00@aaa.example.com"; final var givenRoleToGrant = "package#aaa00.admin";
final var givenAssumedRole = "package#aaa00.admin"; final var givenCurrentUserAsPackageAdmin = new Subject("aaa00@aaa.example.com", givenRoleToGrant);
final var givenAlienPackageAdminRole = "package#aab00.admin"; final var givenAlienPackageAdminRole = findRbacRoleByName("package#aab00.admin");
// when // when
RestAssured // @formatter:off final var result = givenCurrentUserAsPackageAdmin
.given() .grantsRole(givenAlienPackageAdminRole).assumed()
.header("current-user", givenCurrentUserPackageAdmin) .toUser(givenNewUser);
.header("assumed-roles", givenAssumedRole)
.contentType(ContentType.JSON)
.body("""
{
"assumed": true,
"grantedRoleUuid": "%s",
"granteeUserUuid": "%s"
}
""".formatted(
findRbacRoleByName(givenAlienPackageAdminRole).getUuid().toString(),
createRBacUser(givenNewUserName).getUuid().toString())
)
.port(port)
.when()
.post("http://localhost/api/rbac-grants")
.then().assertThat()
.body("message", containsString("Access to granted role"))
.body("message", containsString("forbidden for {package#aaa00.admin}"))
.statusCode(403);
// @formatter:on
// then // then
assertThat(findAllGrantsOfUser(givenCurrentUserPackageAdmin)) result.assertThat()
.extracting(RbacGrantEntity::getGranteeUserName) .body("message", containsString("Access to granted role"))
.doesNotContain(givenNewUserName); .body("message", containsString("forbidden for {package#aaa00.admin}"))
.statusCode(403);
assertThat(findAllGrantsOf(givenCurrentUserAsPackageAdmin))
.extracting(RbacGrantEntity::getGranteeUserName)
.doesNotContain(givenNewUser.getName());
} }
} }
@ -148,87 +116,162 @@ class RbacGrantControllerAcceptanceTest {
@Test @Test
@Accepts({ "GRT:D(Delete)" }) @Accepts({ "GRT:D(Delete)" })
@Transactional(propagation = Propagation.NEVER) @Transactional(propagation = Propagation.NEVER)
void packageAdmin_canRevokePackageAdminRole_grantedByPackageAdmin_toArbitraryUser() { void packageAdmin_canRevokePackageAdminRole_grantedByPackageAdmin_fromArbitraryUser() {
// given // given
final var givenNewUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com"; final var givenArbitraryUser = createRBacUser();
final var givenNewUserNameUuid = createRBacUser(givenNewUserName).getUuid(); final var givenRoleToGrant = "package#aaa00.admin";
final var givenCurrentUserPackageAdmin = "aaa00@aaa.example.com"; final var givenCurrentUserAsPackageAdmin = new Subject("aaa00@aaa.example.com", givenRoleToGrant);
final var givenAssumedRole = "package#aaa00.admin"; final var givenOwnPackageAdminRole = findRbacRoleByName("package#aaa00.admin");
final var givenOwnPackageAdminRole = "package#aaa00.admin";
final var givenOwnPackageAdminRoleUuid = findRbacRoleByName(givenOwnPackageAdminRole).getUuid();
final var expectedGrant = "{ grant assumed role " + givenOwnPackageAdminRole +
" to user " + givenNewUserName +
" by role " + givenAssumedRole + " }";
// and given a grant // and given an existing grant
RestAssured // @formatter:off assumeCreated(givenCurrentUserAsPackageAdmin
.given() .grantsRole(givenOwnPackageAdminRole).assumed()
.header("current-user", givenCurrentUserPackageAdmin) .toUser(givenArbitraryUser));
.header("assumed-roles", givenAssumedRole) assumeGrantExists(
.contentType(ContentType.JSON) givenCurrentUserAsPackageAdmin,
.body(""" "{ grant assumed role %s to user %s by role %s }".formatted(
{ givenOwnPackageAdminRole.getRoleName(),
"assumed": true, givenArbitraryUser.getName(),
"grantedRoleUuid": "%s", givenCurrentUserAsPackageAdmin.assumedRole));
"granteeUserUuid": "%s"
}
""".formatted(
givenOwnPackageAdminRoleUuid.toString(),
givenNewUserNameUuid.toString())
)
.port(port)
.when()
.post("http://localhost/api/rbac-grants")
.then().assertThat()
.statusCode(201); // @formatter:on
assumeThat(findAllGrantsOfUser(givenCurrentUserPackageAdmin))
.extracting(RbacGrantEntity::toDisplay)
.contains(expectedGrant);
// when // when
RestAssured // @formatter:off final var revokeResponse = givenCurrentUserAsPackageAdmin
.given() .revokesRole(givenOwnPackageAdminRole)
.header("current-user", givenCurrentUserPackageAdmin) .fromUser(givenArbitraryUser);
.header("assumed-roles", givenAssumedRole)
.contentType(ContentType.JSON)
.body("""
{
"assumed": true,
"grantedRoleUuid": "%s",
"granteeUserUuid": "%s"
}
""".formatted(
givenOwnPackageAdminRoleUuid.toString(),
givenNewUserNameUuid.toString())
)
.port(port)
.when()
.delete("http://localhost/api/rbac-grants/%s/%s".formatted(
givenOwnPackageAdminRoleUuid, givenNewUserNameUuid
) )
.then().assertThat()
.statusCode(204); // @formatter:on
// then // then
assertThat(findAllGrantsOfUser(givenCurrentUserPackageAdmin)) assertRevoked(revokeResponse);
.extracting(RbacGrantEntity::toDisplay) assertThat(findAllGrantsOf(givenCurrentUserAsPackageAdmin))
.doesNotContain("{ grant assumed role " + givenOwnPackageAdminRole + .extracting(RbacGrantEntity::getGranteeUserName)
" to user " + givenNewUserName + .doesNotContain(givenArbitraryUser.getName());
" by role " + givenAssumedRole + " }");
} }
} }
List<RbacGrantEntity> findAllGrantsOfUser(final String userName) { private void assumeCreated(final ValidatableResponse response) {
assumeThat(response.extract().response().statusCode()).isEqualTo(201);
}
private void assertRevoked(final ValidatableResponse revokeResponse) {
revokeResponse.assertThat().statusCode(204);
}
class Subject {
final String currentUser;
final String assumedRole;
public Subject(final String currentUser, final String assumedRole) {
this.currentUser = currentUser;
this.assumedRole = assumedRole;
}
GrantFixture grantsRole(final RbacRoleEntity givenOwnPackageAdminRole) {
return new GrantFixture(givenOwnPackageAdminRole);
}
RevokeFixture revokesRole(final RbacRoleEntity givenOwnPackageAdminRole) {
return new RevokeFixture(givenOwnPackageAdminRole);
}
class GrantFixture {
private Subject grantingSubject = Subject.this;
private final RbacRoleEntity grantedRole;
private boolean assumed;
private RbacUserEntity granteeUser;
public GrantFixture(final RbacRoleEntity roleToGrant) {
this.grantedRole = roleToGrant;
}
GrantFixture assumed() {
this.assumed = true;
return this;
}
ValidatableResponse toUser(final RbacUserEntity granteeUser) {
this.granteeUser = granteeUser;
return RestAssured // @formatter:ff
.given()
.header("current-user", grantingSubject.currentUser)
.header("assumed-roles", grantingSubject.assumedRole)
.contentType(ContentType.JSON)
.body("""
{
"assumed": true,
"grantedRoleUuid": "%s",
"granteeUserUuid": "%s"
}
""".formatted(
grantedRole.getUuid(),
granteeUser.getUuid())
)
.port(port)
.when()
.post("http://localhost/api/rbac-grants")
.then(); // @formatter:on
}
}
class RevokeFixture {
private Subject currentSubject = Subject.this;
private final RbacRoleEntity grantedRole;
private boolean assumed;
private RbacUserEntity granteeUser;
public RevokeFixture(final RbacRoleEntity roleToGrant) {
this.grantedRole = roleToGrant;
}
ValidatableResponse fromUser(final RbacUserEntity granteeUser) {
this.granteeUser = granteeUser;
return RestAssured // @formatter:ff
.given()
.header("current-user", currentSubject.currentUser)
.header("assumed-roles", currentSubject.assumedRole)
.contentType(ContentType.JSON)
.body("""
{
"assumed": true,
"grantedRoleUuid": "%s",
"granteeUserUuid": "%s"
}
""".formatted(
grantedRole.getUuid(),
granteeUser.getUuid())
)
.port(port)
.when()
.delete("http://localhost/api/rbac-grants/%s/%s".formatted(
grantedRole.getUuid(), granteeUser.getUuid()
))
.then(); // @formatter:on
}
}
}
private void assumeGrantExists(final Subject grantingSubject, final String expectedGrant) {
assumeThat(findAllGrantsOf(grantingSubject))
.extracting(RbacGrantEntity::toDisplay)
.contains(expectedGrant);
}
List<RbacGrantEntity> findAllGrantsOf(final Subject grantingSubject) {
return jpaAttempt.transacted(() -> { return jpaAttempt.transacted(() -> {
context.setCurrentUser(userName); context.setCurrentUser(grantingSubject.currentUser);
return rbacGrantRepository.findAll(); return rbacGrantRepository.findAll();
}).returnedValue(); }).returnedValue();
} }
RbacUserEntity createRBacUser(final String userName) { RbacUserEntity createRBacUser() {
return jpaAttempt.transacted(() -> return jpaAttempt.transacted(() ->
rbacUserRepository.create(new RbacUserEntity(UUID.randomUUID(), userName)) rbacUserRepository.create(new RbacUserEntity(
UUID.randomUUID(),
"test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com"))
).returnedValue(); ).returnedValue();
} }