Fine-grained permissions (#2535)

* Fine-grained permissions

Adds support for permissions of type <permission>(/<rsql filter scope>)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>

* Apply review fixes

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-07-10 13:51:49 +03:00
committed by GitHub
parent 7e8dd046e0
commit 21581c4ea4
69 changed files with 1492 additions and 1487 deletions

View File

@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.app;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import java.util.HashMap;
@@ -47,6 +48,32 @@ class PreAuthorizeEnabledTest extends AbstractSecurityTest {
.andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
}
/**
* Tests whether request returns distribution set if a role with scope is granted for the user
*/
@Test
@WithUser(authorities = { SpPermission.CREATE_REPOSITORY, SpPermission.READ_REPOSITORY + "/name==DsOne" }, autoCreateTenant = false)
void successIfHasRoleWithScope() throws Exception {
createDsOne("successIfHasRoleWithScope");
mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> {
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
assertThat(result.getResponse().getContentAsString()).contains("DsOne");
});
}
/**
* Tests whether request doesn't return distribution set if a role with scope doesn't grant access
*/
@Test
@WithUser(authorities = { SpPermission.CREATE_REPOSITORY, SpPermission.READ_REPOSITORY + "/name==DsOne2" }, autoCreateTenant = false)
void failIfHasNoForbiddingScope() throws Exception {
createDsOne("failIfHasNoForbiddingScope");
mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> {
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
assertThat(result.getResponse().getContentAsString()).doesNotContain("DsOne");
});
}
/**
* Tests whether request succeed if a role is granted for the user
*/
@@ -58,7 +85,7 @@ class PreAuthorizeEnabledTest extends AbstractSecurityTest {
}
/**
* Tests whether read tenant config request fail if a tenant config (or read read) is not granted for the user
* Tests whether read tenant config request fail if a tenant config (or read) is not granted for the user
*/
@Test
@WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
@@ -81,4 +108,17 @@ class PreAuthorizeEnabledTest extends AbstractSecurityTest {
mvc.perform(get("/rest/v1/system/configs"))
.andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
}
private void createDsOne(final String version) throws Exception {
mvc.perform(post("/rest/v1/distributionsets")
.header("Content-Type", "application/json")
.content("""
[
{
"name": "DsOne",
"version": "${version}"
}
]""".replace("${version}", version)))
.andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.CREATED.value()));
}
}