Permission Manager SDK for Java
A Spring Boot SDK for integrating permission management into your Java applications. This library provides a robust and flexible way to manage user permissions across different domains and scopes.
Features
- Annotation-based permission checks
- Programmatic permission management
- Integration with Spring Security
- Support for domain-based permissions
- Scope-based access control
- Multi-domain permission management
- Flexible user ID resolution
Requirements
- Java 21 or higher
- Spring Boot 3.3.0 or higher
- Spring Cloud 2023.0.2 or higher
Installation
Add the following dependency to your pom.xml
:
<dependency>
<groupId>de.mumme-it</groupId>
<artifactId>permission-manager-sdk</artifactId>
<version>0.1.1</version>
</dependency>
Configuration
1. Enable the SDK
Add the @EnablePermissionManager
annotation to your Spring Boot application class:
import de.mummeit.common.annotations.EnablePermissionManager;
@SpringBootApplication
@EnablePermissionManager
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
2. Configuration Properties
Add the following properties to your Spring Boot application properties file (application.yml
or application.properties
):
permission-manager:
base-url: http://your-permission-manager-url # Required: URL of your Permission Manager instance
security:
enabled: true # Optional: Enable/disable security checks (defaults to true)
These properties can be configured in any valid Spring Boot configuration source (application.yml, application.properties, environment variables, etc.) following Spring Boot's standard property resolution order.
Usage
1. Annotation-Based Permission Checks
Use the @RequiresPermission
annotation to protect your methods:
import de.mummeit.pmg.api.annotation.RequiresPermission;
@RestController
@RequestMapping("/api")
public class YourController {
@RequiresPermission(domain = "users", permission = "read", scope = "*")
@GetMapping("/users")
public List<User> getUsers() {
// This method will only execute if the user has the "read" permission in the "users" domain
// The "*" scope means this permission applies to all scopes
return userService.findAll();
}
@RequiresPermission(
domain = "orders",
permission = "update",
scope = "region-#orderId", // Example of prefix-based scope
userIdExpression = "#request.getHeader('X-User-Id')"
)
@PutMapping("/orders/{orderId}")
public Order updateOrder(@PathVariable String orderId, @RequestBody Order order) {
// This method checks permissions with a specific scope and custom user ID resolution
return orderService.update(orderId, order);
}
@RequiresPermission(
domain = "reports",
permission = "view",
scope = "region-*" // Example of wildcard scope matching all regions
)
@GetMapping("/reports")
public List<Report> getReports() {
// This method allows access to users with permission for any region
return reportService.findAll();
}
}
2. Multiple Permission Requirements
You can require multiple permissions using repeated annotations:
@RequiresPermission(domain = "users", permission = "read")
@RequiresPermission(domain = "orders", permission = "write")
public void methodRequiringMultiplePermissions() {
// This method requires both permissions
}
3. Programmatic Permission Management
Use the PermissionManager
class to manage permissions programmatically:
@Service
@RequiredArgsConstructor
public class YourService {
private final PermissionManager permissionManager;
public void grantUserAccess(String userId) {
// Grant access to all user-related operations
permissionManager.grantAccess(
userId,
"users",
List.of("read", "write"),
List.of("user_role"),
"*" // Wildcard scope - applies to all scopes
);
// Grant access to specific region
permissionManager.grantAccess(
userId,
"reports",
List.of("view"),
List.of("reporter"),
"region-europe" // Specific region scope
);
// Grant access to all regions
permissionManager.grantAccess(
userId,
"reports",
List.of("view"),
List.of("global_reporter"),
"region-*" // Wildcard scope - applies to all regions
);
}
public boolean checkAccess(String userId) {
// Check access for all scopes
boolean hasGlobalAccess = permissionManager.hasAccess(
userId,
"users",
"read",
"*"
);
// Check access for specific region
boolean hasRegionAccess = permissionManager.hasAccess(
userId,
"reports",
"view",
"region-europe"
);
return hasGlobalAccess && hasRegionAccess;
}
public void revokeAccess(String userId) {
permissionManager.revokeAccess(
userId,
"users",
List.of("read", "write"),
List.of("user_role"),
"global"
);
}
}
4. Multi-Domain Permission Management
List<Permit> permits = List.of(
new Permit("users", List.of("read"), List.of("user_role")),
new Permit("orders", List.of("write"), List.of("order_manager"))
);
permissionManager.grantMultiDomainAccess(userId, permits, "global");
5. User Permission Queries
List<Permission> userPermissions = permissionManager.findUserPermissions(userId, "global");
Exception Handling
The SDK throws the following exceptions:
AccessDeniedException
: When a permission check failsInvalidPermissionRequestException
: When invalid parameters are providedIntegrationFailedException
: When integration operations fail
Example exception handler:
@ControllerAdvice
public class PermissionExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<String> handleAccessDenied(AccessDeniedException e) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body("Access denied: " + e.getMessage());
}
}
Best Practices
- Scope Usage:
- Use scopes to implement fine-grained access control at the resource level
- Leverage wildcards (
*
) for global access - Use prefix-based wildcards (e.g.,
region-*
) for category-wide access - Be consistent with scope naming conventions (e.g.,
region-europe
,region-asia
)
- User ID Resolution: Customize user ID resolution using SpEL expressions when needed.
- Error Handling: Always handle permission-related exceptions appropriately.
- Permission Granularity: Design permissions with appropriate granularity for your use case.
- Security Context: Ensure proper security context is available when using default user ID resolution.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.