feat: Initial implementation of permission manager SDK - Add core permission management functionality with @RequiresPermission annotation - Implement permission checking aspect with Spring Security integration - Add comprehensive model classes for permissions, roles, and domains - Create integration builder for permission structure setup - Add configuration support for permission manager client - Implement exception handling for access control - Add extensive test coverage with integration tests - Configure Maven build with Spring Boot/Cloud dependencies
This commit is contained in:
@ -0,0 +1,254 @@
|
||||
package de.mummeit.pmg.api;
|
||||
|
||||
import de.mummeit.pmg.api.model.access.request.CheckAccessRequest;
|
||||
import de.mummeit.pmg.api.model.access.request.Permit;
|
||||
import de.mummeit.pmg.api.model.access.request.PermitRequest;
|
||||
import de.mummeit.pmg.api.model.access.request.RevokeScopeAccessRequest;
|
||||
import de.mummeit.pmg.api.model.access.request.RevokeUserAccessRequest;
|
||||
import de.mummeit.pmg.api.model.access.request.SearchPermitRequest;
|
||||
import de.mummeit.pmg.api.model.access.response.PermittedResponse;
|
||||
import de.mummeit.pmg.api.model.integration.DomainIntegration;
|
||||
import de.mummeit.pmg.api.model.integration.Integration;
|
||||
import de.mummeit.pmg.api.model.integration.PermissionIntegration;
|
||||
import de.mummeit.pmg.api.model.integration.RoleIntegration;
|
||||
import de.mummeit.pmg.api.model.integration.RolePermissionRelationIntegration;
|
||||
import de.mummeit.pmg.api.model.structure.Domain;
|
||||
import de.mummeit.pmg.api.model.structure.Permission;
|
||||
import de.mummeit.pmg.api.model.structure.Role;
|
||||
import de.mummeit.utility.BaseIntegrationTest;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class PermissionManagerClientIntegrationTest extends BaseIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private PermissionManagerClient permissionManagerClient;
|
||||
|
||||
private static final String TEST_DOMAIN = "test-domain";
|
||||
private static final String TEST_PERMISSION = "test-permission";
|
||||
private static final String TEST_ROLE = "test-role";
|
||||
private static final String TEST_USER = "test-user";
|
||||
private static final String TEST_SCOPE = "test-scope";
|
||||
|
||||
@Test
|
||||
@DisplayName("should return health status")
|
||||
void getHealthStatus() {
|
||||
String healthStatus = permissionManagerClient.getHealthStatus();
|
||||
assertNotNull(healthStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should successfully perform integrations")
|
||||
void integrationShouldRun() {
|
||||
List<Integration<?>> integrations = List.of(
|
||||
DomainIntegration.builder()
|
||||
.id("1")
|
||||
.action(Integration.Action.create)
|
||||
.data(DomainIntegration.Data.builder()
|
||||
.name("test")
|
||||
.description("test")
|
||||
.build())
|
||||
.build(),
|
||||
PermissionIntegration.builder()
|
||||
.id("2")
|
||||
.action(Integration.Action.create)
|
||||
.data(PermissionIntegration.Data.builder()
|
||||
.domain("test")
|
||||
.name("test")
|
||||
.description("test")
|
||||
.build())
|
||||
.build(),
|
||||
RoleIntegration.builder()
|
||||
.id("3")
|
||||
.action(Integration.Action.create)
|
||||
.data(RoleIntegration.Data.builder()
|
||||
.domain("test")
|
||||
.name("test")
|
||||
.description("test")
|
||||
.build())
|
||||
.build(),
|
||||
RolePermissionRelationIntegration.builder()
|
||||
.id("4")
|
||||
.action(Integration.Action.create)
|
||||
.data(RolePermissionRelationIntegration.Data.builder()
|
||||
.domain("test")
|
||||
.role("test")
|
||||
.permissions(List.of("test"))
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
|
||||
assertDoesNotThrow(() -> permissionManagerClient.performIntegration(integrations));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should manage domains successfully")
|
||||
void domainManagement() {
|
||||
// Create domain
|
||||
Domain domain = new Domain();
|
||||
domain.setName(TEST_DOMAIN);
|
||||
domain.setDescription("Test Domain Description");
|
||||
|
||||
Domain createdDomain = permissionManagerClient.createDomain(domain);
|
||||
assertNotNull(createdDomain);
|
||||
assertEquals(TEST_DOMAIN, createdDomain.getName());
|
||||
|
||||
// Get domain
|
||||
Domain retrievedDomain = permissionManagerClient.getDomain(TEST_DOMAIN);
|
||||
assertNotNull(retrievedDomain);
|
||||
assertEquals(TEST_DOMAIN, retrievedDomain.getName());
|
||||
|
||||
// Update domain
|
||||
domain.setDescription("Updated Description");
|
||||
Domain updatedDomain = permissionManagerClient.updateDomain(TEST_DOMAIN, domain);
|
||||
assertNotNull(updatedDomain);
|
||||
assertEquals("Updated Description", updatedDomain.getDescription());
|
||||
|
||||
// Delete domain
|
||||
assertDoesNotThrow(() -> permissionManagerClient.deleteDomain(TEST_DOMAIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should manage permissions successfully")
|
||||
void permissionManagement() {
|
||||
// First create a domain
|
||||
Domain domain = new Domain();
|
||||
domain.setName(TEST_DOMAIN);
|
||||
domain.setDescription("Test Domain Description");
|
||||
permissionManagerClient.createDomain(domain);
|
||||
|
||||
// Create permission
|
||||
Permission permission = new Permission();
|
||||
permission.setName(TEST_PERMISSION);
|
||||
permission.setDescription("Test Permission Description");
|
||||
|
||||
Permission createdPermission = permissionManagerClient.createPermission(TEST_DOMAIN, permission);
|
||||
assertNotNull(createdPermission);
|
||||
assertEquals(TEST_PERMISSION, createdPermission.getName());
|
||||
|
||||
// Get permission
|
||||
Permission retrievedPermission = permissionManagerClient.getPermission(TEST_DOMAIN, TEST_PERMISSION);
|
||||
assertNotNull(retrievedPermission);
|
||||
assertEquals(TEST_PERMISSION, retrievedPermission.getName());
|
||||
|
||||
// Update permission
|
||||
permission.setDescription("Updated Permission Description");
|
||||
Permission updatedPermission = permissionManagerClient.updatePermission(TEST_DOMAIN, TEST_PERMISSION, permission);
|
||||
assertNotNull(updatedPermission);
|
||||
assertEquals("Updated Permission Description", updatedPermission.getDescription());
|
||||
|
||||
// Delete permission
|
||||
assertDoesNotThrow(() -> permissionManagerClient.deletePermission(TEST_DOMAIN, TEST_PERMISSION));
|
||||
|
||||
// Clean up
|
||||
permissionManagerClient.deleteDomain(TEST_DOMAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should manage roles successfully")
|
||||
void roleManagement() {
|
||||
// First create a domain
|
||||
Domain domain = new Domain();
|
||||
domain.setName(TEST_DOMAIN);
|
||||
domain.setDescription("Test Domain Description");
|
||||
permissionManagerClient.createDomain(domain);
|
||||
|
||||
// Create role
|
||||
Role role = new Role();
|
||||
role.setName(TEST_ROLE);
|
||||
role.setDescription("Test Role Description");
|
||||
role.setPermissions(List.of());
|
||||
|
||||
Role createdRole = permissionManagerClient.createRole(TEST_DOMAIN, role);
|
||||
assertNotNull(createdRole);
|
||||
assertEquals(TEST_ROLE, createdRole.getName());
|
||||
|
||||
// Get role
|
||||
Role retrievedRole = permissionManagerClient.getRole(TEST_DOMAIN, TEST_ROLE);
|
||||
assertNotNull(retrievedRole);
|
||||
assertEquals(TEST_ROLE, retrievedRole.getName());
|
||||
|
||||
// Update role
|
||||
role.setDescription("Updated Role Description");
|
||||
Role updatedRole = permissionManagerClient.updateRole(TEST_DOMAIN, TEST_ROLE, role);
|
||||
assertNotNull(updatedRole);
|
||||
assertEquals("Updated Role Description", updatedRole.getDescription());
|
||||
|
||||
// Delete role
|
||||
assertDoesNotThrow(() -> permissionManagerClient.deleteRole(TEST_DOMAIN, TEST_ROLE));
|
||||
|
||||
// Clean up
|
||||
permissionManagerClient.deleteDomain(TEST_DOMAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should manage access successfully")
|
||||
void accessManagement() {
|
||||
// Setup: Create domain, permission, and role
|
||||
Domain domain = new Domain();
|
||||
domain.setName(TEST_DOMAIN);
|
||||
permissionManagerClient.createDomain(domain);
|
||||
|
||||
Permission permission = new Permission();
|
||||
permission.setName(TEST_PERMISSION);
|
||||
permissionManagerClient.createPermission(TEST_DOMAIN, permission);
|
||||
|
||||
Role role = new Role();
|
||||
role.setName(TEST_ROLE);
|
||||
role.setPermissions(List.of());
|
||||
permissionManagerClient.createRole(TEST_DOMAIN, role);
|
||||
|
||||
// Test permit access
|
||||
PermitRequest permitRequest = new PermitRequest();
|
||||
Permit permit = new Permit();
|
||||
permit.setDomain(TEST_DOMAIN);
|
||||
permit.setRoles(List.of(TEST_ROLE));
|
||||
permit.setPermissions(List.of(TEST_PERMISSION));
|
||||
permitRequest.setPermits(List.of(permit));
|
||||
permitRequest.setUserId(TEST_USER);
|
||||
permitRequest.setScope(TEST_SCOPE);
|
||||
|
||||
assertDoesNotThrow(() -> permissionManagerClient.permitAccess(permitRequest));
|
||||
|
||||
// Test check access
|
||||
CheckAccessRequest checkRequest = new CheckAccessRequest();
|
||||
checkRequest.setDomain(TEST_DOMAIN);
|
||||
checkRequest.setPermission(TEST_PERMISSION);
|
||||
checkRequest.setUserId(TEST_USER);
|
||||
checkRequest.setScope(TEST_SCOPE);
|
||||
|
||||
PermittedResponse response = permissionManagerClient.checkAccess(checkRequest);
|
||||
assertNotNull(response);
|
||||
assertTrue(response.isPermitted());
|
||||
|
||||
// Test search permits
|
||||
SearchPermitRequest searchRequest = new SearchPermitRequest();
|
||||
searchRequest.setUserId(TEST_USER);
|
||||
searchRequest.setScope(TEST_SCOPE);
|
||||
|
||||
List<Permission> permits = permissionManagerClient.searchPermits(searchRequest);
|
||||
assertNotNull(permits);
|
||||
assertFalse(permits.isEmpty());
|
||||
|
||||
// Test revoke access
|
||||
assertDoesNotThrow(() -> permissionManagerClient.revokeAccess(permitRequest));
|
||||
|
||||
// Test revoke scope access
|
||||
RevokeScopeAccessRequest revokeScopeRequest = new RevokeScopeAccessRequest();
|
||||
revokeScopeRequest.setScope(TEST_SCOPE);
|
||||
assertDoesNotThrow(() -> permissionManagerClient.revokeScopeAccess(revokeScopeRequest));
|
||||
|
||||
// Test revoke user access
|
||||
RevokeUserAccessRequest revokeUserRequest = new RevokeUserAccessRequest();
|
||||
revokeUserRequest.setUserId(TEST_USER);
|
||||
assertDoesNotThrow(() -> permissionManagerClient.revokeUserAccess(revokeUserRequest));
|
||||
|
||||
// Clean up
|
||||
permissionManagerClient.deleteDomain(TEST_DOMAIN);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package de.mummeit.pmg.api.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class TestSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
|
||||
return http.build();
|
||||
}
|
||||
}
|
19
src/test/java/de/mummeit/pmg/api/controller/TestConfig.java
Normal file
19
src/test/java/de/mummeit/pmg/api/controller/TestConfig.java
Normal file
@ -0,0 +1,19 @@
|
||||
package de.mummeit.pmg.api.controller;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@EnableWebMvc
|
||||
@EnableAspectJAutoProxy
|
||||
@ComponentScan(basePackages = {
|
||||
"de.mummeit.pmg.api.controller",
|
||||
"de.mummeit.pmg.api.aspect"
|
||||
})
|
||||
public class TestConfig implements WebMvcConfigurer {
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package de.mummeit.pmg.api.controller;
|
||||
|
||||
import de.mummeit.pmg.api.annotation.RequiresPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/test")
|
||||
public class TestController {
|
||||
|
||||
@GetMapping("/resource/{resourceId}")
|
||||
@RequiresPermission(
|
||||
domain = "test-domain",
|
||||
permission = "read",
|
||||
scope = "#resourceId",
|
||||
userIdExpression = "#userId"
|
||||
)
|
||||
public String getResource(@PathVariable String resourceId, @RequestParam String userId) {
|
||||
return "Access granted to resource " + resourceId + " for user " + userId;
|
||||
}
|
||||
|
||||
@PostMapping("/resource/{resourceId}/action")
|
||||
@RequiresPermission(
|
||||
domain = "test-domain",
|
||||
permission = "write",
|
||||
scope = "#resourceId",
|
||||
userIdExpression = "#request.userId"
|
||||
)
|
||||
public String performAction(
|
||||
@PathVariable String resourceId,
|
||||
@RequestBody ActionRequest request
|
||||
) {
|
||||
return "Action performed on resource " + resourceId + " by user " + request.getUserId();
|
||||
}
|
||||
|
||||
@GetMapping("/secured-resource/{resourceId}")
|
||||
@RequiresPermission(
|
||||
domain = "test-domain",
|
||||
permission = "read",
|
||||
scope = "#resourceId"
|
||||
)
|
||||
public String getSecuredResource(@PathVariable String resourceId) {
|
||||
return "Access granted to secured resource " + resourceId;
|
||||
}
|
||||
|
||||
public static class ActionRequest {
|
||||
private String userId;
|
||||
private String action;
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
package de.mummeit.pmg.api.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.mummeit.pmg.api.PermissionManagerClient;
|
||||
import de.mummeit.pmg.api.config.TestSecurityConfig;
|
||||
import de.mummeit.pmg.api.model.access.request.CheckAccessRequest;
|
||||
import de.mummeit.pmg.api.model.access.response.PermittedResponse;
|
||||
import de.mummeit.pmg.api.service.SecurityService;
|
||||
import de.mummeit.pmg.service.exception.AccessDeniedException;
|
||||
import de.mummeit.utility.BaseIntegrationTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
@ComponentScan(basePackages = {
|
||||
"de.mummeit.pmg.api.controller",
|
||||
"de.mummeit.pmg.api.aspect",
|
||||
"de.mummeit.pmg.api.service"
|
||||
})
|
||||
@Import(TestSecurityConfig.class)
|
||||
class TestControllerIntegrationTest extends BaseIntegrationTest {
|
||||
|
||||
@TestConfiguration
|
||||
@EnableWebMvc
|
||||
static class TestConfig {
|
||||
@Bean
|
||||
public TestController testController() {
|
||||
return new TestController();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestExceptionHandler testExceptionHandler() {
|
||||
return new TestExceptionHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityService securityService() {
|
||||
return new SecurityService();
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private PermissionManagerClient permissionManagerClient;
|
||||
|
||||
@Test
|
||||
void getResource_whenPermitted_shouldSucceed() throws Exception {
|
||||
// Given
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(true);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(get("/api/test/resource/123")
|
||||
.param("userId", "user1"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Access granted to resource 123 for user user1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getResource_whenDenied_shouldFail() throws Exception {
|
||||
// Given
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(false);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(get("/api/test/resource/123")
|
||||
.param("userId", "user1"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(result -> result.getResolvedException().getClass().equals(AccessDeniedException.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void performAction_whenPermitted_shouldSucceed() throws Exception {
|
||||
// Given
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(true);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
TestController.ActionRequest request = new TestController.ActionRequest();
|
||||
request.setUserId("user1");
|
||||
request.setAction("test");
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(post("/api/test/resource/123/action")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Action performed on resource 123 by user user1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void performAction_whenDenied_shouldFail() throws Exception {
|
||||
// Given
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(false);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
TestController.ActionRequest request = new TestController.ActionRequest();
|
||||
request.setUserId("user1");
|
||||
request.setAction("test");
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(post("/api/test/resource/123/action")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request)))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(result -> result.getResolvedException().getClass().equals(AccessDeniedException.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSecuredResource_whenPermitted_shouldSucceed() throws Exception {
|
||||
// Given
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken("user1", null)
|
||||
);
|
||||
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(true);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(get("/api/test/secured-resource/123"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Access granted to secured resource 123"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSecuredResource_whenDenied_shouldFail() throws Exception {
|
||||
// Given
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken("user1", null)
|
||||
);
|
||||
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(false);
|
||||
when(permissionManagerClient.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
// When/Then
|
||||
mockMvc.perform(get("/api/test/secured-resource/123"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(result -> result.getResolvedException().getClass().equals(AccessDeniedException.class));
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package de.mummeit.pmg.api.controller;
|
||||
|
||||
import de.mummeit.pmg.service.exception.AccessDeniedException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ControllerAdvice(basePackageClasses = TestController.class)
|
||||
public class TestExceptionHandler {
|
||||
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public void handleAccessDeniedException() {
|
||||
// No response body needed, just return 403 status
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package de.mummeit.pmg.api.service;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SecurityService {
|
||||
|
||||
public String getCurrentUserId() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
throw new IllegalStateException("No authenticated user found");
|
||||
}
|
||||
return authentication.getName();
|
||||
}
|
||||
}
|
260
src/test/java/de/mummeit/pmg/service/PermissionManagerTest.java
Normal file
260
src/test/java/de/mummeit/pmg/service/PermissionManagerTest.java
Normal file
@ -0,0 +1,260 @@
|
||||
package de.mummeit.pmg.service;
|
||||
|
||||
import de.mummeit.pmg.api.PermissionManagerClient;
|
||||
import de.mummeit.pmg.api.model.access.request.*;
|
||||
import de.mummeit.pmg.api.model.access.response.PermittedResponse;
|
||||
import de.mummeit.pmg.api.model.integration.Integration;
|
||||
import de.mummeit.pmg.api.model.structure.Permission;
|
||||
import de.mummeit.pmg.service.exception.AccessDeniedException;
|
||||
import de.mummeit.pmg.service.exception.IntegrationFailedException;
|
||||
import de.mummeit.pmg.service.exception.InvalidPermissionRequestException;
|
||||
import feign.FeignException;
|
||||
import feign.Request;
|
||||
import feign.RequestTemplate;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PermissionManagerTest {
|
||||
|
||||
@Mock
|
||||
private PermissionManagerClient client;
|
||||
|
||||
private PermissionManager permissionManager;
|
||||
|
||||
private static final String TEST_USER = "test-user";
|
||||
private static final String TEST_DOMAIN = "test-domain";
|
||||
private static final String TEST_PERMISSION = "test-permission";
|
||||
private static final String TEST_ROLE = "test-role";
|
||||
private static final String TEST_SCOPE = "test-scope";
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
permissionManager = new PermissionManager(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAccess should return true when user has permission")
|
||||
void hasAccessShouldReturnTrueWhenUserHasPermission() {
|
||||
PermittedResponse response = new PermittedResponse();
|
||||
response.setPermitted(true);
|
||||
when(client.checkAccess(any(CheckAccessRequest.class))).thenReturn(response);
|
||||
|
||||
boolean hasAccess = permissionManager.hasAccess(TEST_USER, TEST_DOMAIN, TEST_PERMISSION, TEST_SCOPE);
|
||||
assertTrue(hasAccess);
|
||||
|
||||
verify(client).checkAccess(any(CheckAccessRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAccess should throw AccessDeniedException when client throws FeignException")
|
||||
void hasAccessShouldThrowAccessDeniedExceptionWhenClientThrowsFeignException() {
|
||||
FeignException feignException = new FeignException.NotFound("Not Found", createRequest(), null, null);
|
||||
when(client.checkAccess(any(CheckAccessRequest.class))).thenThrow(feignException);
|
||||
|
||||
assertThrows(AccessDeniedException.class, () ->
|
||||
permissionManager.hasAccess(TEST_USER, TEST_DOMAIN, TEST_PERMISSION, TEST_SCOPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("hasAccess should throw InvalidPermissionRequestException when parameters are invalid")
|
||||
void hasAccessShouldThrowInvalidPermissionRequestExceptionWhenParametersAreInvalid() {
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.hasAccess(null, TEST_DOMAIN, TEST_PERMISSION, TEST_SCOPE)
|
||||
);
|
||||
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.hasAccess("", TEST_DOMAIN, TEST_PERMISSION, TEST_SCOPE)
|
||||
);
|
||||
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.hasAccess(TEST_USER, null, TEST_PERMISSION, TEST_SCOPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("grantAccess should throw InvalidPermissionRequestException when permissions and roles are empty")
|
||||
void grantAccessShouldThrowInvalidPermissionRequestExceptionWhenPermissionsAndRolesAreEmpty() {
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.grantAccess(TEST_USER, TEST_DOMAIN, Collections.emptyList(), Collections.emptyList(), TEST_SCOPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("performIntegration should throw IntegrationFailedException when client throws exception")
|
||||
void performIntegrationShouldThrowIntegrationFailedExceptionWhenClientThrowsException() {
|
||||
List<Integration<?>> integrations = Collections.singletonList(mock(Integration.class));
|
||||
FeignException feignException = new FeignException.InternalServerError("Internal Server Error", createRequest(), null, null);
|
||||
doThrow(feignException).when(client).performIntegration(any());
|
||||
|
||||
IntegrationFailedException exception = assertThrows(IntegrationFailedException.class, () ->
|
||||
permissionManager.performIntegration(integrations)
|
||||
);
|
||||
|
||||
assertEquals(integrations, exception.getFailedIntegrations());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("grantMultiDomainAccess should validate permits")
|
||||
void grantMultiDomainAccessShouldValidatePermits() {
|
||||
Permit invalidPermit = new Permit();
|
||||
invalidPermit.setDomain(""); // Invalid domain
|
||||
List<Permit> permits = Collections.singletonList(invalidPermit);
|
||||
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.grantMultiDomainAccess(TEST_USER, permits, TEST_SCOPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("revokeMultiDomainAccess should validate permits")
|
||||
void revokeMultiDomainAccessShouldValidatePermits() {
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.revokeMultiDomainAccess(TEST_USER, null, TEST_SCOPE)
|
||||
);
|
||||
|
||||
assertThrows(InvalidPermissionRequestException.class, () ->
|
||||
permissionManager.revokeMultiDomainAccess(TEST_USER, Collections.emptyList(), TEST_SCOPE)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("grantAccess should call client with correct request")
|
||||
void grantAccessShouldCallClientWithCorrectRequest() {
|
||||
List<String> permissions = Collections.singletonList(TEST_PERMISSION);
|
||||
List<String> roles = Collections.singletonList(TEST_ROLE);
|
||||
|
||||
permissionManager.grantAccess(TEST_USER, TEST_DOMAIN, permissions, roles, TEST_SCOPE);
|
||||
|
||||
verify(client).permitAccess(argThat(request -> {
|
||||
Permit permit = request.getPermits().get(0);
|
||||
return TEST_USER.equals(request.getUserId()) &&
|
||||
TEST_SCOPE.equals(request.getScope()) &&
|
||||
TEST_DOMAIN.equals(permit.getDomain()) &&
|
||||
permit.getPermissions().contains(TEST_PERMISSION) &&
|
||||
permit.getRoles().contains(TEST_ROLE);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("revokeAccess should call client with correct request")
|
||||
void revokeAccessShouldCallClientWithCorrectRequest() {
|
||||
List<String> permissions = Collections.singletonList(TEST_PERMISSION);
|
||||
List<String> roles = Collections.singletonList(TEST_ROLE);
|
||||
|
||||
permissionManager.revokeAccess(TEST_USER, TEST_DOMAIN, permissions, roles, TEST_SCOPE);
|
||||
|
||||
verify(client).revokeAccess(argThat(request -> {
|
||||
Permit permit = request.getPermits().get(0);
|
||||
return TEST_USER.equals(request.getUserId()) &&
|
||||
TEST_SCOPE.equals(request.getScope()) &&
|
||||
TEST_DOMAIN.equals(permit.getDomain()) &&
|
||||
permit.getPermissions().contains(TEST_PERMISSION) &&
|
||||
permit.getRoles().contains(TEST_ROLE);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("revokeAllUserAccess should call client with correct request")
|
||||
void revokeAllUserAccessShouldCallClientWithCorrectRequest() {
|
||||
permissionManager.revokeAllUserAccess(TEST_USER);
|
||||
|
||||
verify(client).revokeUserAccess(argThat(request ->
|
||||
TEST_USER.equals(request.getUserId())
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("revokeAllScopeAccess should call client with correct request")
|
||||
void revokeAllScopeAccessShouldCallClientWithCorrectRequest() {
|
||||
permissionManager.revokeAllScopeAccess(TEST_SCOPE);
|
||||
|
||||
verify(client).revokeScopeAccess(argThat(request ->
|
||||
TEST_SCOPE.equals(request.getScope())
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("findUserPermissions should return permissions from client")
|
||||
void findUserPermissionsShouldReturnPermissionsFromClient() {
|
||||
Permission permission = new Permission();
|
||||
permission.setName(TEST_PERMISSION);
|
||||
List<Permission> expectedPermissions = Collections.singletonList(permission);
|
||||
|
||||
when(client.searchPermits(any(SearchPermitRequest.class))).thenReturn(expectedPermissions);
|
||||
|
||||
List<Permission> actualPermissions = permissionManager.findUserPermissions(TEST_USER, TEST_SCOPE);
|
||||
|
||||
assertEquals(expectedPermissions, actualPermissions);
|
||||
verify(client).searchPermits(argThat(request ->
|
||||
TEST_USER.equals(request.getUserId()) &&
|
||||
TEST_SCOPE.equals(request.getScope())
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("grantMultiDomainAccess should call client with correct request")
|
||||
void grantMultiDomainAccessShouldCallClientWithCorrectRequest() {
|
||||
Permit permit1 = new Permit();
|
||||
permit1.setDomain(TEST_DOMAIN);
|
||||
permit1.setPermissions(Collections.singletonList(TEST_PERMISSION));
|
||||
permit1.setRoles(Collections.singletonList(TEST_ROLE));
|
||||
|
||||
Permit permit2 = new Permit();
|
||||
permit2.setDomain(TEST_DOMAIN + "-2");
|
||||
permit2.setPermissions(Collections.singletonList(TEST_PERMISSION + "-2"));
|
||||
permit2.setRoles(Collections.singletonList(TEST_ROLE + "-2"));
|
||||
|
||||
List<Permit> permits = Arrays.asList(permit1, permit2);
|
||||
|
||||
permissionManager.grantMultiDomainAccess(TEST_USER, permits, TEST_SCOPE);
|
||||
|
||||
verify(client).permitAccess(argThat(request ->
|
||||
TEST_USER.equals(request.getUserId()) &&
|
||||
TEST_SCOPE.equals(request.getScope()) &&
|
||||
request.getPermits().equals(permits)
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("revokeMultiDomainAccess should call client with correct request")
|
||||
void revokeMultiDomainAccessShouldCallClientWithCorrectRequest() {
|
||||
Permit permit1 = new Permit();
|
||||
permit1.setDomain(TEST_DOMAIN);
|
||||
permit1.setPermissions(Collections.singletonList(TEST_PERMISSION));
|
||||
permit1.setRoles(Collections.singletonList(TEST_ROLE));
|
||||
|
||||
Permit permit2 = new Permit();
|
||||
permit2.setDomain(TEST_DOMAIN + "-2");
|
||||
permit2.setPermissions(Collections.singletonList(TEST_PERMISSION + "-2"));
|
||||
permit2.setRoles(Collections.singletonList(TEST_ROLE + "-2"));
|
||||
|
||||
List<Permit> permits = Arrays.asList(permit1, permit2);
|
||||
|
||||
permissionManager.revokeMultiDomainAccess(TEST_USER, permits, TEST_SCOPE);
|
||||
|
||||
verify(client).revokeAccess(argThat(request ->
|
||||
TEST_USER.equals(request.getUserId()) &&
|
||||
TEST_SCOPE.equals(request.getScope()) &&
|
||||
request.getPermits().equals(permits)
|
||||
));
|
||||
}
|
||||
|
||||
private Request createRequest() {
|
||||
return Request.create(Request.HttpMethod.GET, "url", new HashMap<>(), null, new RequestTemplate());
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
package de.mummeit.pmg.service.builder;
|
||||
|
||||
import de.mummeit.pmg.api.model.integration.*;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class IntegrationBuilderTest {
|
||||
|
||||
private static final String TEST_DOMAIN = "test-domain";
|
||||
private static final String TEST_DESCRIPTION = "test-description";
|
||||
private static final String TEST_PERMISSION = "test-permission";
|
||||
private static final String TEST_ROLE = "test-role";
|
||||
|
||||
@Test
|
||||
@DisplayName("should build domain integrations")
|
||||
void shouldBuildDomainIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof DomainIntegration);
|
||||
DomainIntegration domainIntegration = (DomainIntegration) integration;
|
||||
assertEquals(Integration.Action.create, domainIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, domainIntegration.getData().getName());
|
||||
assertEquals(TEST_DESCRIPTION, domainIntegration.getData().getDescription());
|
||||
assertEquals("domain:" + TEST_DOMAIN + ":create", domainIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should update domain integrations")
|
||||
void shouldUpdateDomainIntegrations() {
|
||||
String newName = "new-domain";
|
||||
String newDescription = "Updated Description";
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.updateDomain(TEST_DOMAIN, newName, newDescription)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(2, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof DomainIntegration);
|
||||
DomainIntegration domainIntegration = (DomainIntegration) integration;
|
||||
assertEquals(Integration.Action.update, domainIntegration.getAction());
|
||||
assertEquals(newName, domainIntegration.getData().getName());
|
||||
assertEquals(TEST_DOMAIN, domainIntegration.getData().getOldName());
|
||||
assertEquals(newDescription, domainIntegration.getData().getDescription());
|
||||
assertEquals("domain:" + TEST_DOMAIN + ":update", domainIntegration.getId());
|
||||
|
||||
PermissionIntegration permissionIntegration = (PermissionIntegration) integrations.get(1);
|
||||
assertEquals(newName, permissionIntegration.getData().getDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should delete domain integrations")
|
||||
void shouldDeleteDomainIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.deleteDomain(TEST_DOMAIN)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof DomainIntegration);
|
||||
DomainIntegration domainIntegration = (DomainIntegration) integration;
|
||||
assertEquals(Integration.Action.delete, domainIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, domainIntegration.getData().getName());
|
||||
assertEquals("domain:" + TEST_DOMAIN + ":delete", domainIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build permission integrations")
|
||||
void shouldBuildPermissionIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(2, integrations.size());
|
||||
Integration<?> integration = integrations.get(1);
|
||||
assertTrue(integration instanceof PermissionIntegration);
|
||||
PermissionIntegration permissionIntegration = (PermissionIntegration) integration;
|
||||
assertEquals(Integration.Action.create, permissionIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, permissionIntegration.getData().getDomain());
|
||||
assertEquals(TEST_PERMISSION, permissionIntegration.getData().getName());
|
||||
assertEquals(TEST_DESCRIPTION, permissionIntegration.getData().getDescription());
|
||||
assertEquals("permission:" + TEST_DOMAIN + ":" + TEST_PERMISSION + ":create", permissionIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should update permission integrations")
|
||||
void shouldUpdatePermissionIntegrations() {
|
||||
String newName = "new-permission";
|
||||
String newDescription = "Updated Permission";
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.selectDomain(TEST_DOMAIN)
|
||||
.updatePermission(TEST_PERMISSION, newName, newDescription)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof PermissionIntegration);
|
||||
PermissionIntegration permissionIntegration = (PermissionIntegration) integration;
|
||||
assertEquals(Integration.Action.update, permissionIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, permissionIntegration.getData().getDomain());
|
||||
assertEquals(newName, permissionIntegration.getData().getName());
|
||||
assertEquals(TEST_PERMISSION, permissionIntegration.getData().getOldName());
|
||||
assertEquals(newDescription, permissionIntegration.getData().getDescription());
|
||||
assertEquals("permission:" + TEST_DOMAIN + ":" + TEST_PERMISSION + ":update", permissionIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should remove permission integrations")
|
||||
void shouldRemovePermissionIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.selectDomain(TEST_DOMAIN)
|
||||
.removePermission(TEST_PERMISSION)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof PermissionIntegration);
|
||||
PermissionIntegration permissionIntegration = (PermissionIntegration) integration;
|
||||
assertEquals(Integration.Action.delete, permissionIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, permissionIntegration.getData().getDomain());
|
||||
assertEquals(TEST_PERMISSION, permissionIntegration.getData().getName());
|
||||
assertEquals("permission:" + TEST_DOMAIN + ":" + TEST_PERMISSION + ":delete", permissionIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build role integrations")
|
||||
void shouldBuildRoleIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addRole(TEST_ROLE, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(2, integrations.size());
|
||||
Integration<?> integration = integrations.get(1);
|
||||
assertTrue(integration instanceof RoleIntegration);
|
||||
RoleIntegration roleIntegration = (RoleIntegration) integration;
|
||||
assertEquals(Integration.Action.create, roleIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, roleIntegration.getData().getDomain());
|
||||
assertEquals(TEST_ROLE, roleIntegration.getData().getName());
|
||||
assertEquals(TEST_DESCRIPTION, roleIntegration.getData().getDescription());
|
||||
assertEquals("role:" + TEST_DOMAIN + ":" + TEST_ROLE + ":create", roleIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should update role integrations")
|
||||
void shouldUpdateRoleIntegrations() {
|
||||
String newName = "new-role";
|
||||
String newDescription = "Updated Role";
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.selectDomain(TEST_DOMAIN)
|
||||
.updateRole(TEST_ROLE, newName, newDescription)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof RoleIntegration);
|
||||
RoleIntegration roleIntegration = (RoleIntegration) integration;
|
||||
assertEquals(Integration.Action.update, roleIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, roleIntegration.getData().getDomain());
|
||||
assertEquals(newName, roleIntegration.getData().getName());
|
||||
assertEquals(TEST_ROLE, roleIntegration.getData().getOldName());
|
||||
assertEquals(newDescription, roleIntegration.getData().getDescription());
|
||||
assertEquals("role:" + TEST_DOMAIN + ":" + TEST_ROLE + ":update", roleIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should remove role integrations")
|
||||
void shouldRemoveRoleIntegrations() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.selectDomain(TEST_DOMAIN)
|
||||
.removeRole(TEST_ROLE)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
Integration<?> integration = integrations.get(0);
|
||||
assertTrue(integration instanceof RoleIntegration);
|
||||
RoleIntegration roleIntegration = (RoleIntegration) integration;
|
||||
assertEquals(Integration.Action.delete, roleIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, roleIntegration.getData().getDomain());
|
||||
assertEquals(TEST_ROLE, roleIntegration.getData().getName());
|
||||
assertEquals("role:" + TEST_DOMAIN + ":" + TEST_ROLE + ":delete", roleIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build role permission relation integrations")
|
||||
void shouldBuildRolePermissionRelationIntegrations() {
|
||||
List<String> permissions = Arrays.asList(TEST_PERMISSION, TEST_PERMISSION + "-2");
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.assignPermissionsToRole(TEST_ROLE, permissions)
|
||||
.build();
|
||||
|
||||
assertEquals(2, integrations.size());
|
||||
Integration<?> integration = integrations.get(1);
|
||||
assertTrue(integration instanceof RolePermissionRelationIntegration);
|
||||
RolePermissionRelationIntegration relationIntegration = (RolePermissionRelationIntegration) integration;
|
||||
assertEquals(Integration.Action.create, relationIntegration.getAction());
|
||||
assertEquals(TEST_DOMAIN, relationIntegration.getData().getDomain());
|
||||
assertEquals(TEST_ROLE, relationIntegration.getData().getRole());
|
||||
assertEquals(permissions, relationIntegration.getData().getPermissions());
|
||||
assertEquals("role-permissions:" + TEST_DOMAIN + ":" + TEST_ROLE + ":" + String.join(",", permissions) + ":create", relationIntegration.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should build multiple integrations in sequence")
|
||||
void shouldBuildMultipleIntegrationsInSequence() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.addRole(TEST_ROLE, TEST_DESCRIPTION)
|
||||
.assignPermissionsToRole(TEST_ROLE, Arrays.asList(TEST_PERMISSION))
|
||||
.build();
|
||||
|
||||
assertEquals(4, integrations.size());
|
||||
assertTrue(integrations.get(0) instanceof DomainIntegration);
|
||||
assertTrue(integrations.get(1) instanceof PermissionIntegration);
|
||||
assertTrue(integrations.get(2) instanceof RoleIntegration);
|
||||
assertTrue(integrations.get(3) instanceof RolePermissionRelationIntegration);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should throw exception when no domain context is set")
|
||||
void shouldThrowExceptionWhenNoDomainContextIsSet() {
|
||||
assertThrows(IllegalStateException.class, () ->
|
||||
IntegrationBuilder.create().addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should allow switching domain context")
|
||||
void shouldAllowSwitchingDomainContext() {
|
||||
String secondDomain = "second-domain";
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.createDomain(secondDomain, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(4, integrations.size());
|
||||
PermissionIntegration firstPermission = (PermissionIntegration) integrations.get(1);
|
||||
PermissionIntegration secondPermission = (PermissionIntegration) integrations.get(3);
|
||||
assertEquals(TEST_DOMAIN, firstPermission.getData().getDomain());
|
||||
assertEquals(secondDomain, secondPermission.getData().getDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should allow selecting domain without creating it")
|
||||
void shouldAllowSelectingDomainWithoutCreatingIt() {
|
||||
List<Integration<?>> integrations = IntegrationBuilder.create()
|
||||
.selectDomain(TEST_DOMAIN)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(1, integrations.size());
|
||||
PermissionIntegration permission = (PermissionIntegration) integrations.get(0);
|
||||
assertEquals(TEST_DOMAIN, permission.getData().getDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should generate consistent IDs for same integrations")
|
||||
void shouldGenerateConsistentIdsForSameIntegrations() {
|
||||
List<Integration<?>> firstRun = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
List<Integration<?>> secondRun = IntegrationBuilder.create()
|
||||
.createDomain(TEST_DOMAIN, TEST_DESCRIPTION)
|
||||
.addPermission(TEST_PERMISSION, TEST_DESCRIPTION)
|
||||
.build();
|
||||
|
||||
assertEquals(firstRun.get(0).getId(), secondRun.get(0).getId());
|
||||
assertEquals(firstRun.get(1).getId(), secondRun.get(1).getId());
|
||||
}
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package de.mummeit.pmg.service.config;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.mummeit.pmg.api.model.integration.DomainIntegration;
|
||||
import de.mummeit.pmg.api.model.integration.Integration;
|
||||
import de.mummeit.pmg.service.PermissionManager;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AbstractPermissionManagerConfigurationTest {
|
||||
|
||||
@Mock
|
||||
private PermissionManager permissionManager;
|
||||
|
||||
@Mock
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Mock
|
||||
private Resource resource;
|
||||
|
||||
@Mock
|
||||
private ApplicationReadyEvent event;
|
||||
|
||||
private TestPermissionManagerConfiguration configuration;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
configuration = new TestPermissionManagerConfiguration(
|
||||
permissionManager,
|
||||
resourceLoader,
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should perform programmatic integrations on startup")
|
||||
void shouldPerformProgrammaticIntegrationsOnStartup() {
|
||||
// Given
|
||||
List<Integration<?>> integrations = Collections.singletonList(
|
||||
DomainIntegration.builder()
|
||||
.id("1")
|
||||
.action(Integration.Action.create)
|
||||
.data(DomainIntegration.Data.builder()
|
||||
.name("test")
|
||||
.description("test")
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
configuration.setProgrammaticIntegrations(integrations);
|
||||
|
||||
// When
|
||||
configuration.performIntegrationsOnStartup();
|
||||
|
||||
// Then
|
||||
verify(permissionManager).performIntegration(integrations);
|
||||
verify(resourceLoader, never()).getResource(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should perform JSON integrations on startup")
|
||||
void shouldPerformJsonIntegrationsOnStartup() throws IOException {
|
||||
// Given
|
||||
List<Integration<?>> integrations = Collections.singletonList(
|
||||
DomainIntegration.builder()
|
||||
.id("1")
|
||||
.action(Integration.Action.create)
|
||||
.data(DomainIntegration.Data.builder()
|
||||
.name("test")
|
||||
.description("test")
|
||||
.build())
|
||||
.build()
|
||||
);
|
||||
|
||||
configuration.setProgrammaticIntegrations(null);
|
||||
configuration.setJsonPath("classpath:integrations.json");
|
||||
|
||||
when(resourceLoader.getResource("classpath:integrations.json")).thenReturn(resource);
|
||||
when(resource.getInputStream()).thenReturn(new ByteArrayInputStream("[]".getBytes()));
|
||||
doReturn(integrations).when(objectMapper).readValue(any(InputStream.class), any(TypeReference.class));
|
||||
|
||||
// When
|
||||
configuration.performIntegrationsOnStartup();
|
||||
|
||||
// Then
|
||||
verify(permissionManager).performIntegration(integrations);
|
||||
verify(resourceLoader).getResource("classpath:integrations.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("should handle no integrations gracefully")
|
||||
void shouldHandleNoIntegrationsGracefully() {
|
||||
// Given
|
||||
configuration.setProgrammaticIntegrations(null);
|
||||
configuration.setJsonPath(null);
|
||||
|
||||
// When
|
||||
configuration.performIntegrationsOnStartup();
|
||||
|
||||
// Then
|
||||
verify(permissionManager, never()).performIntegration(any());
|
||||
verify(resourceLoader, never()).getResource(any());
|
||||
}
|
||||
|
||||
private static class TestPermissionManagerConfiguration extends AbstractPermissionManagerConfiguration {
|
||||
private List<Integration<?>> programmaticIntegrations;
|
||||
private String jsonPath;
|
||||
|
||||
public TestPermissionManagerConfiguration(
|
||||
PermissionManager permissionManager,
|
||||
ResourceLoader resourceLoader,
|
||||
ObjectMapper objectMapper
|
||||
) {
|
||||
super(permissionManager, resourceLoader, objectMapper);
|
||||
}
|
||||
|
||||
public void setProgrammaticIntegrations(List<Integration<?>> integrations) {
|
||||
this.programmaticIntegrations = integrations;
|
||||
}
|
||||
|
||||
public void setJsonPath(String path) {
|
||||
this.jsonPath = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integration<?>> getIntegrations() {
|
||||
return programmaticIntegrations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getIntegrationsJsonPath() {
|
||||
return jsonPath;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user