implements REST API DELETE to /api/rbac-grants/{grantedRoleUuid}/{granteeUserUuid}:
This commit is contained in:
parent
787400c089
commit
8a62d9802e
@ -60,4 +60,22 @@ public class RbacGrantController implements RbacgrantsApi {
|
|||||||
return ResponseEntity.created(uri).build();
|
return ResponseEntity.created(uri).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ResponseEntity<Void> revokeRoleFromUser(
|
||||||
|
final String currentUser,
|
||||||
|
final String assumedRoles,
|
||||||
|
final UUID grantedRoleUuid,
|
||||||
|
final UUID granteeUserUuid) {
|
||||||
|
|
||||||
|
context.setCurrentUser(currentUser);
|
||||||
|
if (assumedRoles != null && !assumedRoles.isBlank()) {
|
||||||
|
context.assumeRoles(assumedRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbacGrantRepository.deleteByRbacGrantId(new RbacGrantId(granteeUserUuid, grantedRoleUuid));
|
||||||
|
|
||||||
|
return ResponseEntity.noContent().build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,10 @@ public class RbacGrantEntity {
|
|||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
private RbacRoleType grantedRoleType;
|
private RbacRoleType grantedRoleType;
|
||||||
|
|
||||||
|
RbacGrantId getRbacGrantId() {
|
||||||
|
return new RbacGrantId(granteeUserUuid, grantedRoleUuid);
|
||||||
|
}
|
||||||
|
|
||||||
public String toDisplay() {
|
public String toDisplay() {
|
||||||
return "{ grant " + (assumed ? "assumed " : "") +
|
return "{ grant " + (assumed ? "assumed " : "") +
|
||||||
"role " + grantedRoleIdName + " to user " + granteeUserName + " by role " + grantedByRoleIdName + " }";
|
"role " + grantedRoleIdName + " to user " + granteeUserName + " by role " + grantedByRoleIdName + " }";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.rbac.rbacgrant;
|
package net.hostsharing.hsadminng.rbac.rbacgrant;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
@ -10,6 +11,7 @@ import java.util.UUID;
|
|||||||
@Getter
|
@Getter
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class RbacGrantId implements Serializable {
|
public class RbacGrantId implements Serializable {
|
||||||
|
|
||||||
private UUID granteeUserUuid;
|
private UUID granteeUserUuid;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.rbac.rbacgrant;
|
package net.hostsharing.hsadminng.rbac.rbacgrant;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.Repository;
|
import org.springframework.data.repository.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -10,5 +12,11 @@ public interface RbacGrantRepository extends Repository<RbacGrantEntity, RbacGra
|
|||||||
|
|
||||||
void save(final RbacGrantEntity grant);
|
void save(final RbacGrantEntity grant);
|
||||||
|
|
||||||
void delete(final RbacGrantEntity grant);
|
@Modifying
|
||||||
|
@Query(value = """
|
||||||
|
delete from RbacGrantEntity as g
|
||||||
|
where g.grantedRoleUuid=:#{#rbacGrantId.grantedRoleUuid}
|
||||||
|
and g.granteeUserUuid=:#{#rbacGrantId.granteeUserUuid}
|
||||||
|
""")
|
||||||
|
void deleteByRbacGrantId(RbacGrantId rbacGrantId);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@ paths:
|
|||||||
/api/rbac-grants:
|
/api/rbac-grants:
|
||||||
$ref: "./api-definition/rbac-grants.yaml"
|
$ref: "./api-definition/rbac-grants.yaml"
|
||||||
|
|
||||||
|
/api/rbac-grants/{grantedRoleUuid}/{granteeUserUuid}:
|
||||||
|
$ref: "./api-definition/rbac-grants-id.yaml"
|
||||||
|
|
||||||
# HS
|
# HS
|
||||||
|
|
||||||
/api/customers:
|
/api/customers:
|
||||||
|
30
src/main/resources/api-definition/rbac-grants-id.yaml
Normal file
30
src/main/resources/api-definition/rbac-grants-id.yaml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- rbacgrants
|
||||||
|
operationId: revokeRoleFromUser
|
||||||
|
parameters:
|
||||||
|
- $ref: './api-definition/auth.yaml#/components/parameters/currentUser'
|
||||||
|
- $ref: './api-definition/auth.yaml#/components/parameters/assumedRoles'
|
||||||
|
- name: grantedRoleUuid
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: UUID of the granted role.
|
||||||
|
- name: granteeUserUuid
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
description: UUID of the user to whom the role was granted.
|
||||||
|
responses:
|
||||||
|
"204":
|
||||||
|
description: No Content
|
||||||
|
"401":
|
||||||
|
$ref: './api-definition/error-responses.yaml#/components/responses/Unauthorized'
|
||||||
|
"403":
|
||||||
|
$ref: './api-definition/error-responses.yaml#/components/responses/Forbidden'
|
||||||
|
"404":
|
||||||
|
$ref: './api-definition/error-responses.yaml#/components/responses/NotFound'
|
@ -31,6 +31,7 @@ post:
|
|||||||
responses:
|
responses:
|
||||||
"201":
|
"201":
|
||||||
description: OK
|
description: OK
|
||||||
|
content:
|
||||||
"401":
|
"401":
|
||||||
$ref: './api-definition/error-responses.yaml#/components/responses/Unauthorized'
|
$ref: './api-definition/error-responses.yaml#/components/responses/Unauthorized'
|
||||||
"403":
|
"403":
|
||||||
|
@ -142,6 +142,83 @@ class RbacGrantControllerAcceptanceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class RevokeRoleFromUser {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Accepts({ "GRT:D(Delete)" })
|
||||||
|
@Transactional(propagation = Propagation.NEVER)
|
||||||
|
void packageAdmin_canRevokePackageAdminRole_grantedByPackageAdmin_toArbitraryUser() {
|
||||||
|
|
||||||
|
// given
|
||||||
|
final var givenNewUserName = "test-user-" + RandomStringUtils.randomAlphabetic(8) + "@example.com";
|
||||||
|
final var givenNewUserNameUuid = createRBacUser(givenNewUserName).getUuid();
|
||||||
|
final var givenCurrentUserPackageAdmin = "aaa00@aaa.example.com";
|
||||||
|
final var givenAssumedRole = "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
|
||||||
|
RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-user", givenCurrentUserPackageAdmin)
|
||||||
|
.header("assumed-roles", givenAssumedRole)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("""
|
||||||
|
{
|
||||||
|
"assumed": true,
|
||||||
|
"grantedRoleUuid": "%s",
|
||||||
|
"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
|
||||||
|
RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-user", givenCurrentUserPackageAdmin)
|
||||||
|
.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
|
||||||
|
assertThat(findAllGrantsOfUser(givenCurrentUserPackageAdmin))
|
||||||
|
.extracting(RbacGrantEntity::toDisplay)
|
||||||
|
.doesNotContain("{ grant assumed role " + givenOwnPackageAdminRole +
|
||||||
|
" to user " + givenNewUserName +
|
||||||
|
" by role " + givenAssumedRole + " }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<RbacGrantEntity> findAllGrantsOfUser(final String userName) {
|
List<RbacGrantEntity> findAllGrantsOfUser(final String userName) {
|
||||||
return jpaAttempt.transacted(() -> {
|
return jpaAttempt.transacted(() -> {
|
||||||
context.setCurrentUser(userName);
|
context.setCurrentUser(userName);
|
||||||
|
@ -132,7 +132,9 @@ class RbacGrantRepositoryIntegrationTest {
|
|||||||
@Transactional(propagation = Propagation.NEVER)
|
@Transactional(propagation = Propagation.NEVER)
|
||||||
public void packageAdmin_canNotGrantPackageOwnerRole() {
|
public void packageAdmin_canNotGrantPackageOwnerRole() {
|
||||||
// given
|
// given
|
||||||
record Given(RbacUserEntity arbitraryUser, UUID packageOwnerRoleUuid) {}
|
record Given(RbacUserEntity arbitraryUser, UUID packageOwnerRoleUuid) {
|
||||||
|
|
||||||
|
}
|
||||||
final var given = jpaAttempt.transacted(() -> {
|
final var given = jpaAttempt.transacted(() -> {
|
||||||
// to find the uuids of we need to have access rights to these
|
// to find the uuids of we need to have access rights to these
|
||||||
currentUser("admin@aaa.example.com");
|
currentUser("admin@aaa.example.com");
|
||||||
@ -184,7 +186,7 @@ class RbacGrantRepositoryIntegrationTest {
|
|||||||
currentUser("admin@aaa.example.com");
|
currentUser("admin@aaa.example.com");
|
||||||
assumedRoles("customer#aaa.admin");
|
assumedRoles("customer#aaa.admin");
|
||||||
final var revokeAttempt = attempt(em, () -> {
|
final var revokeAttempt = attempt(em, () -> {
|
||||||
rbacGrantRepository.delete(grant);
|
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -207,7 +209,7 @@ class RbacGrantRepositoryIntegrationTest {
|
|||||||
currentUser("aaa00@aaa.example.com");
|
currentUser("aaa00@aaa.example.com");
|
||||||
assumedRoles("package#aaa00.admin");
|
assumedRoles("package#aaa00.admin");
|
||||||
final var revokeAttempt = attempt(em, () -> {
|
final var revokeAttempt = attempt(em, () -> {
|
||||||
rbacGrantRepository.delete(grant);
|
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -231,7 +233,7 @@ class RbacGrantRepositoryIntegrationTest {
|
|||||||
currentUser("aaa00@aaa.example.com");
|
currentUser("aaa00@aaa.example.com");
|
||||||
assumedRoles("package#aaa00.admin");
|
assumedRoles("package#aaa00.admin");
|
||||||
final var revokeAttempt = attempt(em, () -> {
|
final var revokeAttempt = attempt(em, () -> {
|
||||||
rbacGrantRepository.delete(grant);
|
rbacGrantRepository.deleteByRbacGrantId(grant.getRbacGrantId());
|
||||||
});
|
});
|
||||||
|
|
||||||
// then
|
// then
|
||||||
|
Loading…
Reference in New Issue
Block a user