├── .devcontainer ├── .env.example ├── Dockerfile ├── backup.sh ├── backup.sh.example ├── devcontainer.json └── docker-compose.yml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── SECURITY.md ├── copilot-instructions.md └── pull_request_template.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── build.gradle ├── gradle ├── .DS_Store └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── readme.md ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── spacecodee │ │ └── springbootsecurityopentemplate │ │ ├── SpringbootSecurityOpenTemplateApplication.java │ │ ├── config │ │ ├── AopConfig.java │ │ ├── JacksonConfig.java │ │ ├── JwtConfig.java │ │ ├── SwaggerConfig.java │ │ ├── WebConfig.java │ │ └── converter │ │ │ └── StringToMapConverter.java │ │ ├── constants │ │ ├── ApiConstants.java │ │ └── SecurityConstants.java │ │ ├── controller │ │ ├── api │ │ │ ├── auth │ │ │ │ ├── IAuthController.java │ │ │ │ ├── impl │ │ │ │ │ └── AuthControllerImpl.java │ │ │ │ └── package-info.java │ │ │ ├── core │ │ │ │ ├── IModuleController.java │ │ │ │ ├── IOperationController.java │ │ │ │ ├── IPermissionController.java │ │ │ │ ├── IRoleController.java │ │ │ │ └── impl │ │ │ │ │ ├── ModuleControllerImpl.java │ │ │ │ │ ├── OperationControllerImpl.java │ │ │ │ │ ├── PermissionControllerImpl.java │ │ │ │ │ └── RoleControllerImpl.java │ │ │ ├── package-info.java │ │ │ ├── security │ │ │ │ ├── IPermissionJwtController.java │ │ │ │ └── impl │ │ │ │ │ └── PermissionJwtControllerImpl.java │ │ │ └── user │ │ │ │ ├── IUserController.java │ │ │ │ ├── developer │ │ │ │ ├── IDeveloperController.java │ │ │ │ ├── impl │ │ │ │ │ └── DeveloperControllerImpl.java │ │ │ │ └── package-info.java │ │ │ │ ├── editor │ │ │ │ ├── IEditorController.java │ │ │ │ └── impl │ │ │ │ │ └── EditorControllerImpl.java │ │ │ │ ├── guest │ │ │ │ ├── IGuestController.java │ │ │ │ └── impl │ │ │ │ │ └── GuestControllerImpl.java │ │ │ │ ├── impl │ │ │ │ └── UserControllerImpl.java │ │ │ │ ├── manager │ │ │ │ ├── IManagerController.java │ │ │ │ └── impl │ │ │ │ │ └── ManagerControllerImpl.java │ │ │ │ ├── package-info.java │ │ │ │ ├── system │ │ │ │ └── admin │ │ │ │ │ ├── ISystemAdminController.java │ │ │ │ │ └── impl │ │ │ │ │ └── SystemAdminControllerImpl.java │ │ │ │ └── viewer │ │ │ │ ├── IViewerController.java │ │ │ │ └── impl │ │ │ │ └── ViewerControllerImpl.java │ │ └── base │ │ │ ├── AbstractController.java │ │ │ └── package-info.java │ │ ├── data │ │ ├── base │ │ │ └── IJwtTokenFields.java │ │ ├── common │ │ │ ├── auth │ │ │ │ └── AuthenticationResponsePojo.java │ │ │ └── response │ │ │ │ ├── ApiErrorDataPojo.java │ │ │ │ ├── ApiErrorPojo.java │ │ │ │ ├── ApiResponseDataPojo.java │ │ │ │ ├── ApiResponsePojo.java │ │ │ │ └── BaseResponsePojo.java │ │ ├── dto │ │ │ ├── auth │ │ │ │ ├── AuthResponseDTO.java │ │ │ │ ├── JwtTokenDTO.java │ │ │ │ └── SecurityJwtTokenDTO.java │ │ │ ├── base │ │ │ │ └── BaseAuditDTO.java │ │ │ ├── core │ │ │ │ ├── module │ │ │ │ │ └── ModuleDTO.java │ │ │ │ ├── operation │ │ │ │ │ ├── OperationDTO.java │ │ │ │ │ └── OperationDetailDTO.java │ │ │ │ ├── permission │ │ │ │ │ ├── PermissionDTO.java │ │ │ │ │ └── PermissionDetailDTO.java │ │ │ │ └── role │ │ │ │ │ ├── RoleDTO.java │ │ │ │ │ └── RoleDetailDTO.java │ │ │ ├── security │ │ │ │ ├── JwtTokenSecurityDTO.java │ │ │ │ ├── ModuleSecurityDTO.java │ │ │ │ ├── OperationSecurityDTO.java │ │ │ │ ├── OperationSecurityPathDTO.java │ │ │ │ ├── PermissionSecurityDTO.java │ │ │ │ ├── RoleSecurityDTO.java │ │ │ │ └── UserSecurityDTO.java │ │ │ └── user │ │ │ │ ├── UserDTO.java │ │ │ │ ├── UserDetailDTO.java │ │ │ │ ├── UserProfileDTO.java │ │ │ │ ├── developer │ │ │ │ ├── DeveloperDTO.java │ │ │ │ └── DeveloperDetailDTO.java │ │ │ │ ├── editor │ │ │ │ ├── EditorDTO.java │ │ │ │ └── EditorDetailDTO.java │ │ │ │ ├── guest │ │ │ │ ├── GuestDTO.java │ │ │ │ └── GuestDetailDTO.java │ │ │ │ ├── manager │ │ │ │ ├── ManagerDTO.java │ │ │ │ └── ManagerDetailDTO.java │ │ │ │ ├── system │ │ │ │ └── admin │ │ │ │ │ ├── SystemAdminDTO.java │ │ │ │ │ └── SystemAdminDetailDTO.java │ │ │ │ └── viewer │ │ │ │ ├── ViewerDTO.java │ │ │ │ └── ViewerDetailDTO.java │ │ ├── record │ │ │ ├── TokenClaims.java │ │ │ ├── TokenEvent.java │ │ │ ├── TokenStateChangeEvent.java │ │ │ ├── TokenValidationResult.java │ │ │ └── ValidationError.java │ │ └── vo │ │ │ ├── auth │ │ │ └── LoginVO.java │ │ │ ├── core │ │ │ ├── module │ │ │ │ ├── CreateModuleVO.java │ │ │ │ ├── ModuleFilterVO.java │ │ │ │ └── UpdateModuleVO.java │ │ │ ├── operation │ │ │ │ ├── CreateOperationVO.java │ │ │ │ ├── OperationFilterVO.java │ │ │ │ └── UpdateOperationVO.java │ │ │ ├── permission │ │ │ │ ├── CreatePermissionVO.java │ │ │ │ ├── PermissionFilterVO.java │ │ │ │ └── UpdatePermissionVO.java │ │ │ └── role │ │ │ │ ├── CreateRoleVO.java │ │ │ │ ├── RoleFilterVO.java │ │ │ │ └── UpdateRoleVO.java │ │ │ ├── jwt │ │ │ ├── CreateJwtTokenVO.java │ │ │ └── UpdateJwtTokenVO.java │ │ │ └── user │ │ │ ├── developer │ │ │ ├── CreateDeveloperVO.java │ │ │ ├── DeveloperFilterVO.java │ │ │ └── UpdateDeveloperVO.java │ │ │ ├── editor │ │ │ ├── CreateEditorVO.java │ │ │ ├── EditorFilterVO.java │ │ │ └── UpdateEditorVO.java │ │ │ ├── guest │ │ │ ├── CreateGuestVO.java │ │ │ ├── GuestFilterVO.java │ │ │ └── UpdateGuestVO.java │ │ │ ├── manager │ │ │ ├── CreateManagerVO.java │ │ │ ├── ManagerFilterVO.java │ │ │ └── UpdateManagerVO.java │ │ │ ├── system │ │ │ └── admin │ │ │ │ ├── CreateSystemAdminVO.java │ │ │ │ ├── SystemAdminFilterVO.java │ │ │ │ └── UpdateSystemAdminVO.java │ │ │ └── viewer │ │ │ ├── CreateViewerVO.java │ │ │ ├── UpdateViewerVO.java │ │ │ └── ViewerFilterVO.java │ │ ├── enums │ │ ├── PasswordValidationRule.java │ │ ├── RoleEnum.java │ │ ├── RolePermissionEnum.java │ │ └── TokenStateEnum.java │ │ ├── exceptions │ │ ├── auth │ │ │ ├── AccessDeniedException.java │ │ │ ├── InvalidCredentialsException.java │ │ │ ├── InvalidPasswordComplexityException.java │ │ │ ├── InvalidPasswordException.java │ │ │ ├── UnauthorizedException.java │ │ │ ├── jwt │ │ │ │ ├── JwtTokenAuthenticationException.java │ │ │ │ ├── JwtTokenClaimsInvalidException.java │ │ │ │ ├── JwtTokenClaimsMissingException.java │ │ │ │ ├── JwtTokenException.java │ │ │ │ ├── JwtTokenExpiredException.java │ │ │ │ ├── JwtTokenHeaderAlgException.java │ │ │ │ ├── JwtTokenHeaderDecodeException.java │ │ │ │ ├── JwtTokenHeaderFormatException.java │ │ │ │ ├── JwtTokenHeaderTypeException.java │ │ │ │ ├── JwtTokenHeaderValidationException.java │ │ │ │ ├── JwtTokenInvalidException.java │ │ │ │ ├── JwtTokenInvalidFormatException.java │ │ │ │ ├── JwtTokenInvalidSignatureException.java │ │ │ │ ├── JwtTokenMalformedException.java │ │ │ │ ├── JwtTokenMissingClaimException.java │ │ │ │ ├── JwtTokenNotFoundException.java │ │ │ │ ├── JwtTokenSignatureException.java │ │ │ │ ├── JwtTokenUnexpectedException.java │ │ │ │ └── JwtTokenValidationException.java │ │ │ ├── package-info.java │ │ │ └── ratelimit │ │ │ │ ├── RateLimitExceededException.java │ │ │ │ └── RateLimitException.java │ │ ├── base │ │ │ └── BaseException.java │ │ ├── endpoint │ │ │ ├── ModuleNotFoundException.java │ │ │ ├── OperationNotFoundException.java │ │ │ ├── PermissionNotFoundException.java │ │ │ └── package-info.java │ │ ├── handler │ │ │ └── GlobalExceptionHandler.java │ │ ├── locale │ │ │ └── LocaleResolutionException.java │ │ ├── operation │ │ │ ├── CannotSaveException.java │ │ │ ├── NoContentException.java │ │ │ ├── NoCreatedException.java │ │ │ ├── NoDeletedException.java │ │ │ ├── NoDisabledException.java │ │ │ ├── NoUpdatedException.java │ │ │ └── package-info.java │ │ ├── user │ │ │ ├── LastAdminException.java │ │ │ ├── LastClientException.java │ │ │ ├── LastDeveloperException.java │ │ │ ├── LastTechnicianException.java │ │ │ ├── RoleNotFoundException.java │ │ │ ├── UserNotFoundException.java │ │ │ ├── UsernameAlreadyExistsException.java │ │ │ ├── UsernameNotFoundException.java │ │ │ └── package-info.java │ │ ├── util │ │ │ ├── ExceptionShortComponent.java │ │ │ └── MessageParameterUtil.java │ │ └── validation │ │ │ ├── AlreadyExistsException.java │ │ │ ├── DoNotExistsByIdException.java │ │ │ ├── IllegalArgumentException.java │ │ │ ├── InvalidParameterException.java │ │ │ ├── ObjectNotFoundException.java │ │ │ ├── PasswordDoNotMatchException.java │ │ │ ├── ValidationException.java │ │ │ └── package-info.java │ │ ├── language │ │ ├── MessageConfig.java │ │ ├── MessageParameterHandler.java │ │ ├── MessageResolverService.java │ │ ├── MessageUtilComponent.java │ │ ├── config │ │ │ └── LocaleConfig.java │ │ └── constant │ │ │ └── LanguageConstants.java │ │ ├── mappers │ │ ├── core │ │ │ ├── IModuleMapper.java │ │ │ ├── IOperationMapper.java │ │ │ ├── IPermissionMapper.java │ │ │ └── IRoleMapper.java │ │ ├── security │ │ │ ├── IJwtTokenSecurityMapper.java │ │ │ ├── IModuleSecurityMapper.java │ │ │ ├── IOperationSecurityMapper.java │ │ │ ├── IPermissionSecurityMapper.java │ │ │ ├── IRoleSecurityMapper.java │ │ │ ├── IUserSecurityMapper.java │ │ │ └── auth │ │ │ │ └── IAuthMapper.java │ │ └── user │ │ │ ├── IUserMapper.java │ │ │ ├── developer │ │ │ └── IDeveloperMapper.java │ │ │ ├── editor │ │ │ └── IEditorMapper.java │ │ │ ├── guest │ │ │ └── IGuestMapper.java │ │ │ ├── manager │ │ │ └── IManagerMapper.java │ │ │ ├── system │ │ │ └── admin │ │ │ │ └── ISystemAdminMapper.java │ │ │ └── viewer │ │ │ └── IViewerMapper.java │ │ ├── persistence │ │ ├── entity │ │ │ ├── BaseAuditEntity.java │ │ │ ├── JwtTokenEntity.java │ │ │ ├── ModuleEntity.java │ │ │ ├── OperationEntity.java │ │ │ ├── PermissionEntity.java │ │ │ ├── RoleEntity.java │ │ │ └── UserEntity.java │ │ └── repository │ │ │ ├── core │ │ │ ├── IModuleRepository.java │ │ │ ├── IOperationRepository.java │ │ │ ├── IPermissionRepository.java │ │ │ └── IRoleRepository.java │ │ │ ├── security │ │ │ ├── jwt │ │ │ │ └── IJwtTokenSecurityRepository.java │ │ │ ├── operation │ │ │ │ └── IOperationSecurityRepository.java │ │ │ └── user │ │ │ │ └── IUserSecurityRepository.java │ │ │ └── user │ │ │ ├── IDeveloperRepository.java │ │ │ ├── IEditorRepository.java │ │ │ ├── IGuestRepository.java │ │ │ ├── IManagerRepository.java │ │ │ ├── ISystemAdminRepository.java │ │ │ ├── IUserRepository.java │ │ │ └── IViewerRepository.java │ │ ├── security │ │ ├── authentication │ │ │ └── filter │ │ │ │ ├── JwtAuthenticationFilter.java │ │ │ │ ├── LocaleResolverFilter.java │ │ │ │ └── RateLimitFilter.java │ │ ├── authorization │ │ │ ├── evaluator │ │ │ │ └── CustomPermissionEvaluator.java │ │ │ └── manager │ │ │ │ └── CustomAuthorizationManager.java │ │ ├── config │ │ │ ├── CorsConfig.java │ │ │ ├── CustomSecurityHeadersConfigurer.java │ │ │ ├── HttpSecurityConfig.java │ │ │ ├── MethodSecurityConfig.java │ │ │ └── PasswordEncoderConfig.java │ │ ├── handler │ │ │ ├── CustomAccessDeniedHandler.java │ │ │ ├── CustomAuthenticationEntryPoint.java │ │ │ └── CustomAuthenticationSuccessHandler.java │ │ ├── path │ │ │ ├── ISecurityPathService.java │ │ │ └── impl │ │ │ │ └── SecurityPathServiceImpl.java │ │ └── util │ │ │ └── SecurityUtils.java │ │ ├── service │ │ ├── core │ │ │ ├── module │ │ │ │ ├── IModuleService.java │ │ │ │ └── impl │ │ │ │ │ └── ModuleServiceImpl.java │ │ │ ├── operation │ │ │ │ ├── IOperationService.java │ │ │ │ └── impl │ │ │ │ │ └── OperationServiceImpl.java │ │ │ ├── package-info.java │ │ │ ├── permission │ │ │ │ ├── IPermissionService.java │ │ │ │ └── impl │ │ │ │ │ └── PermissionServiceImpl.java │ │ │ └── role │ │ │ │ ├── IRoleService.java │ │ │ │ └── impl │ │ │ │ └── RoleServiceImpl.java │ │ ├── security │ │ │ ├── auth │ │ │ │ ├── IAuthService.java │ │ │ │ └── impl │ │ │ │ │ └── AuthServiceImpl.java │ │ │ ├── operation │ │ │ │ ├── IOperationSecurityService.java │ │ │ │ └── impl │ │ │ │ │ └── OperationSecurityServiceImpl.java │ │ │ ├── package-info.java │ │ │ ├── token │ │ │ │ ├── IJwtProviderService.java │ │ │ │ ├── IJwtTokenSecurityService.java │ │ │ │ ├── builder │ │ │ │ │ ├── ITokenBuilderService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenBuilderServiceImpl.java │ │ │ │ ├── cleanup │ │ │ │ │ ├── ITokenCleanupService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenCleanupServiceImpl.java │ │ │ │ ├── facade │ │ │ │ │ └── TokenOperationsFacade.java │ │ │ │ ├── impl │ │ │ │ │ ├── JwtProviderServiceImpl.java │ │ │ │ │ └── JwtTokenSecurityServiceImpl.java │ │ │ │ ├── key │ │ │ │ │ ├── IJwtKeyService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── JwtKeyServiceImpl.java │ │ │ │ ├── lifecycle │ │ │ │ │ ├── ITokenLifecycleService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenLifecycleServiceImpl.java │ │ │ │ ├── ratelimit │ │ │ │ │ ├── ITokenRateLimitService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenRateLimitServiceImpl.java │ │ │ │ ├── repository │ │ │ │ │ ├── ITokenRepositoryService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenRepositoryServiceImpl.java │ │ │ │ ├── state │ │ │ │ │ ├── ITokenStateService.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── TokenStateServiceImpl.java │ │ │ │ └── validation │ │ │ │ │ ├── ITokenValidatorService.java │ │ │ │ │ └── impl │ │ │ │ │ ├── TokenClaimsValidatorImpl.java │ │ │ │ │ ├── TokenExpirationValidatorImpl.java │ │ │ │ │ ├── TokenFormatValidatorServiceImpl.java │ │ │ │ │ ├── TokenHeaderValidatorImpl.java │ │ │ │ │ ├── TokenSignatureValidatorImpl.java │ │ │ │ │ └── TokenValidationChainImpl.java │ │ │ └── user │ │ │ │ ├── IUserSecurityService.java │ │ │ │ └── impl │ │ │ │ └── UserSecurityServiceImpl.java │ │ └── user │ │ │ ├── IUserService.java │ │ │ ├── developer │ │ │ ├── IDeveloperService.java │ │ │ └── impl │ │ │ │ └── DeveloperServiceImpl.java │ │ │ ├── editor │ │ │ ├── IEditorService.java │ │ │ └── impl │ │ │ │ └── EditorServiceImpl.java │ │ │ ├── guest │ │ │ ├── IGuestService.java │ │ │ └── impl │ │ │ │ └── GuestServiceImpl.java │ │ │ ├── impl │ │ │ └── UserServiceImpl.java │ │ │ ├── manager │ │ │ ├── IManagerService.java │ │ │ └── impl │ │ │ │ └── ManagerServiceImpl.java │ │ │ ├── system │ │ │ └── admin │ │ │ │ ├── ISystemAdminService.java │ │ │ │ └── impl │ │ │ │ └── SystemAdminServiceImpl.java │ │ │ └── viewer │ │ │ ├── IViewerService.java │ │ │ └── impl │ │ │ └── ViewerServiceImpl.java │ │ └── utils │ │ ├── LocaleUtils.java │ │ └── PathUtils.java └── resources │ ├── api │ └── api-doc.properties │ ├── application-local.properties.example │ ├── application.properties │ ├── data │ └── full_backup.sql │ ├── locale │ ├── message.properties │ └── message_es.properties │ ├── logback-spring.xml │ └── validation │ ├── validation.properties │ └── validation_es.properties └── test └── java └── com └── spacecodee └── springbootsecurityopentemplate └── SpringbootSecurityOpenTemplateApplicationTests.java /.devcontainer/.env.example: -------------------------------------------------------------------------------- 1 | POSTGRES_USER=#your-database-user 2 | POSTGRES_PASSWORD=#your-database-password 3 | POSTGRES_DB=#your-database-name 4 | SPRING_PROFILES_ACTIVE=#your-spring-profile-local,dev,ect 5 | JAVA_VERSION=21 6 | GRADLE_VERSION=8.10.2 -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/devcontainers/java:21-bookworm 2 | 3 | # Install required packages including native libraries 4 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 5 | && apt-get -y install --no-install-recommends \ 6 | build-essential \ 7 | gcc \ 8 | libc6-dev \ 9 | libstdc++6 \ 10 | postgresql-client \ 11 | && apt-get clean -y \ 12 | && rm -rf /var/lib/apt/lists/* 13 | 14 | ARG GRADLE_VERSION=8.10.2 15 | RUN su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle ${GRADLE_VERSION}" \ 16 | && mkdir -p /home/vscode/.gradle \ 17 | && chown -R vscode:vscode /home/vscode/.gradle 18 | 19 | # Set workspace permissions 20 | RUN mkdir -p /workspace && chown -R vscode:vscode /workspace 21 | 22 | USER vscode -------------------------------------------------------------------------------- /.devcontainer/backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Define the backup file name and path 4 | BACKUP_FILE="../src/main/resources/data/full_backup.sql" 5 | 6 | # Check if docker-compose.yml exists in the current directory 7 | if [ ! -f docker-compose.yml ]; then 8 | echo "docker-compose.yml not found in the current directory." 9 | exit 1 10 | fi 11 | 12 | # Run the pg_dump command inside the db container with --inserts option 13 | docker-compose exec db pg_dump --username=spacecodee --dbname=springboot_security_open_template --inserts > $BACKUP_FILE 14 | 15 | echo "Backup completed: $BACKUP_FILE" -------------------------------------------------------------------------------- /.devcontainer/backup.sh.example: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Define the backup file name and path 4 | BACKUP_FILE="../src/main/resources/data/full_backup.sql" 5 | 6 | # Check if docker-compose.yml exists in the current directory 7 | if [ ! -f docker-compose.yml ]; then 8 | echo "docker-compose.yml not found in the current directory." 9 | exit 1 10 | fi 11 | 12 | # Run the pg_dump command inside the db container 13 | docker-compose exec db pg_dump --username="$POSTGRES_USER" --dbname="$POSTGRES_DB" --inserts > $BACKUP_FILE 14 | 15 | echo "Backup completed: $BACKUP_FILE" -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Spring Boot Dev Environment", 3 | "dockerComposeFile": "docker-compose.yml", 4 | "service": "app", 5 | "workspaceFolder": "/workspace", // Changed from /workspaces/ 6 | "customizations": { 7 | "vscode": { 8 | "extensions": [ 9 | "vscjava.vscode-java-pack", 10 | "vmware.vscode-spring-boot", 11 | "vscjava.vscode-gradle", 12 | "redhat.vscode-yaml", 13 | "gabrielbb.vscode-lombok", 14 | "pverest.java-ide-pack" 15 | ] 16 | }, 17 | "jetbrains": { 18 | "backend": "IntelliJ" 19 | } 20 | }, 21 | "features": { 22 | "ghcr.io/devcontainers/features/java": { 23 | "version": "21", 24 | "installGradle": true, 25 | "gradleVersion": "8.10.2" 26 | } 27 | }, 28 | "forwardPorts": [ 29 | 8080 30 | ], 31 | "postCreateCommand": "gradle wrapper && ./gradlew build -x test", 32 | "remoteUser": "vscode", 33 | // IntelliJ specific settings 34 | "remoteEnv": { 35 | "JAVA_HOME": "/usr/local/sdkman/candidates/java/current" 36 | }, 37 | "hostRequirements": { 38 | "memory": "8gb" 39 | }, 40 | "otherPortsAttributes": { 41 | "onAutoForward": "ignore" 42 | } 43 | } -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | name: springboot_security_open_template 2 | 3 | services: 4 | app: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | args: 9 | GRADLE_VERSION: "${GRADLE_VERSION:-8.10.2}" 10 | volumes: 11 | - ../:/workspace:cached,Z 12 | - gradle-cache:/home/vscode/.gradle/ 13 | command: sleep infinity 14 | env_file: 15 | - .env 16 | environment: 17 | POSTGRES_USER: ${POSTGRES_USER} 18 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} 19 | POSTGRES_DB: ${POSTGRES_DB} 20 | SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE} 21 | JAVA_HOME: /usr/local/sdkman/candidates/java/current 22 | GRADLE_VERSION: ${GRADLE_VERSION} 23 | depends_on: 24 | - db 25 | networks: 26 | - spring-network 27 | 28 | db: 29 | container_name: postgres_db 30 | image: postgres:17.2-bookworm 31 | restart: unless-stopped 32 | volumes: 33 | - postgres-data:/var/lib/postgresql/data 34 | env_file: 35 | - .env 36 | environment: 37 | POSTGRES_USER: ${POSTGRES_USER} 38 | POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} 39 | POSTGRES_DB: ${POSTGRES_DB} 40 | networks: 41 | - spring-network 42 | 43 | networks: 44 | spring-network: 45 | driver: bridge 46 | 47 | volumes: 48 | postgres-data: 49 | gradle-cache: 50 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /gradlew text eol=lf 2 | *.bat text eol=crlf 3 | *.jar binary 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '[BUG] ' 5 | labels: 'bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Make request to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots/Logs** 24 | If applicable, add screenshots or logs to help explain your problem. 25 | 26 | **Environment:** 27 | - OS: [e.g. Ubuntu 22.04] 28 | - JDK Version: [e.g. 21] 29 | - Project Version: [e.g. 1.0.0] 30 | - Browser/Tool: [e.g. Postman v10.21] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug Report 2 | description: File a bug report 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: Thanks for taking the time to fill out this bug report! 7 | contact_links: 8 | - name: Security Issue 9 | url: mailto:spacecodee@gmail.com 10 | about: Please report security vulnerabilities directly to the maintainers 11 | - name: Question or Discussion 12 | url: https://github.com/your-username/spring-security-jwt-template/discussions 13 | about: Please ask and answer questions here 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '[FEATURE] ' 5 | labels: 'enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | 22 | **Implementation considerations** 23 | - [ ] Security implications 24 | - [ ] Performance impact 25 | - [ ] Backward compatibility 26 | - [ ] Required testing 27 | -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacecodee/springboot-security-open-template/70ce3df7d2452583d83ed4023a2779ff51c40644/.github/copilot-instructions.md -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | Please include a summary of the change and which issue is fixed. Include relevant motivation and context. 3 | 4 | Fixes # (issue) 5 | 6 | ## Type of change 7 | Please delete options that are not relevant. 8 | 9 | - [ ] Bug fix (non-breaking change which fixes an issue) 10 | - [ ] New feature (non-breaking change which adds functionality) 11 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 12 | - [ ] Documentation update 13 | 14 | ## Checklist: 15 | Before submitting your PR, please review the following checklist: 16 | 17 | - [ ] My code follows the style guidelines of this project 18 | - [ ] I have performed a self-review of my own code 19 | - [ ] I have commented my code, particularly in hard-to-understand areas 20 | - [ ] I have made corresponding changes to the documentation 21 | - [ ] My changes generate no new warnings 22 | - [ ] I have added tests that prove my fix is effective or that my feature works 23 | - [ ] New and existing unit tests pass locally with my changes 24 | - [ ] Any dependent changes have been merged and published in downstream modules 25 | 26 | ## Security Checklist: 27 | If your changes involve security-sensitive features: 28 | 29 | - [ ] Input validation has been implemented 30 | - [ ] Authentication checks are in place where needed 31 | - [ ] Authorization controls have been implemented 32 | - [ ] Sensitive data is properly handled and secured 33 | - [ ] Security testing has been performed 34 | 35 | ## Additional Information: 36 | Add any other context about the pull request here. 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .devcontainer/.env 3 | /src/main/resources/application-local.properties 4 | error.log 5 | error.json 6 | .github/copilot-instructions.md 7 | cache-impl.md 8 | 9 | HELP.md 10 | .gradle 11 | build/ 12 | !gradle/wrapper/gradle-wrapper.jar 13 | !**/src/main/**/build/ 14 | !**/src/test/**/build/ 15 | .devcontainer/backup.sh 16 | 17 | ### STS ### 18 | .apt_generated 19 | .classpath 20 | .factorypath 21 | .project 22 | .settings 23 | .springBeans 24 | .sts4-cache 25 | bin/ 26 | !**/src/main/**/bin/ 27 | !**/src/test/**/bin/ 28 | 29 | ### IntelliJ IDEA ### 30 | .idea 31 | *.iws 32 | *.iml 33 | *.ipr 34 | out/ 35 | !**/src/main/**/out/ 36 | !**/src/test/**/out/ 37 | 38 | ### NetBeans ### 39 | /nbproject/private/ 40 | /nbbuild/ 41 | /dist/ 42 | /nbdist/ 43 | /.nb-gradle/ 44 | 45 | ### VS Code ### 46 | .vscode/ 47 | -------------------------------------------------------------------------------- /gradle/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacecodee/springboot-security-open-template/70ce3df7d2452583d83ed4023a2779ff51c40644/gradle/.DS_Store -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacecodee/springboot-security-open-template/70ce3df7d2452583d83ed4023a2779ff51c40644/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'springboot-security-open-template' 2 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/SpringbootSecurityOpenTemplateApplication.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringbootSecurityOpenTemplateApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringbootSecurityOpenTemplateApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/AopConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 5 | 6 | @Configuration 7 | @EnableAspectJAutoProxy(exposeProxy = true) 8 | public class AopConfig { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/JacksonConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.SerializationFeature; 9 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 10 | 11 | @Configuration 12 | public class JacksonConfig { 13 | @Bean 14 | public ObjectMapper objectMapper() { 15 | ObjectMapper objectMapper = new ObjectMapper(); 16 | objectMapper.registerModule(new JavaTimeModule()); 17 | objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 18 | objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 19 | return objectMapper; 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/JwtConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config; 2 | 3 | import io.jsonwebtoken.JwtParser; 4 | import io.jsonwebtoken.Jwts; 5 | import jakarta.annotation.PostConstruct; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 13 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.key.IJwtKeyService; 14 | 15 | import java.util.Base64; 16 | 17 | @Configuration 18 | @RequiredArgsConstructor 19 | public class JwtConfig { 20 | 21 | private final IJwtKeyService jwtKeyService; 22 | private final ExceptionShortComponent exceptionShortComponent; 23 | 24 | @Value("${security.jwt.secret-key}") 25 | private String secretKey; 26 | 27 | @PostConstruct 28 | public void validateConfiguration() { 29 | try { 30 | byte[] keyBytes = Base64.getDecoder().decode(secretKey); 31 | if (!this.jwtKeyService.isValidKey(keyBytes)) { 32 | throw this.exceptionShortComponent.tokenInvalidException("auth.token.key.invalid"); 33 | } 34 | } catch (IllegalArgumentException e) { 35 | throw this.exceptionShortComponent.tokenInvalidException("auth.token.key.error", e.getMessage()); 36 | } 37 | } 38 | 39 | @Bean 40 | JwtParser jwtParser() { 41 | return Jwts.parser() 42 | .verifyWith(this.jwtKeyService.generateKey()) 43 | .build(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config; 2 | 3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 4 | import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; 5 | import io.swagger.v3.oas.annotations.info.Contact; 6 | import io.swagger.v3.oas.annotations.info.Info; 7 | import io.swagger.v3.oas.annotations.info.License; 8 | import io.swagger.v3.oas.annotations.security.SecurityScheme; 9 | import io.swagger.v3.oas.annotations.servers.Server; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | @Configuration 13 | @OpenAPIDefinition(info = @Info(title = "Spring Security JWT Template API", version = "1.0", description = "REST API for managing users, roles and permissions", contact = @Contact(name = "spacecodee", email = "spacecodee@gmail.com", url = "https://github.com/spacecodee"), license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0")), servers = { 14 | @Server(url = "/api/v1", description = "Default Server URL") 15 | }) 16 | @SecurityScheme(name = "bearerAuth", type = SecuritySchemeType.HTTP, bearerFormat = "JWT", scheme = "bearer") 17 | public class SwaggerConfig { 18 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.config.converter.StringToMapConverter; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.format.FormatterRegistry; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | @Configuration 10 | public class WebConfig implements WebMvcConfigurer { 11 | 12 | @Override 13 | public void addFormatters(@NotNull FormatterRegistry registry) { 14 | registry.addConverter(new StringToMapConverter()); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/config/converter/StringToMapConverter.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.config.converter; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.core.type.TypeReference; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.springframework.core.convert.converter.Converter; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | @Slf4j 14 | public class StringToMapConverter implements Converter> { 15 | 16 | private final ObjectMapper objectMapper = new ObjectMapper(); 17 | 18 | @Override 19 | public Map convert(@NotNull String source) { 20 | if (source.trim().isEmpty()) { 21 | return new HashMap<>(); 22 | } 23 | 24 | try { 25 | TypeReference> typeRef = new TypeReference<>() { 26 | }; 27 | return objectMapper.readValue(source, typeRef); 28 | } catch (JsonProcessingException e) { 29 | log.error("Error converting string to map: {}", source, e); 30 | throw new IllegalArgumentException("Invalid metadata format: " + source); 31 | } catch (Exception e) { 32 | log.error("Unexpected error converting string to map: {}", source, e); 33 | return new HashMap<>(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/constants/ApiConstants.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.constants; 2 | 3 | public class ApiConstants { 4 | 5 | private ApiConstants() { 6 | throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); 7 | } 8 | 9 | public static final String API_BASE_PATH = "/api/v1"; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/constants/SecurityConstants.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.constants; 2 | 3 | import java.util.List; 4 | 5 | public final class SecurityConstants { 6 | 7 | private static final String[] SWAGGER_PATHS_ARRAY = { 8 | "/swagger-ui", 9 | "/v3/api-docs", 10 | "/swagger-resources", 11 | "/webjars/swagger-ui" 12 | }; 13 | 14 | private static final String[] ERROR_PATHS_ARRAY = { 15 | "/error", 16 | "/api/v1/error" 17 | }; 18 | 19 | public static final List SWAGGER_PATHS = List.of(SecurityConstants.SWAGGER_PATHS_ARRAY); 20 | 21 | public static final List ERROR_PATHS = List.of(SecurityConstants.ERROR_PATHS_ARRAY); 22 | 23 | public static final String REFRESH_TOKEN_PATH = "/auth/refresh-token"; 24 | 25 | private SecurityConstants() { 26 | throw new IllegalStateException("Utility class"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/auth/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains authentication related controllers. 3 | * Handles login, logout, token validation and refresh operations. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.controller.api.auth; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Root package for all API controllers. 3 | * Controllers are organized by domain and functionality. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.controller.api; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/security/IPermissionJwtController.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.controller.api.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.common.response.ApiResponseDataPojo; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.permission.PermissionDetailDTO; 5 | import io.swagger.v3.oas.annotations.Operation; 6 | import io.swagger.v3.oas.annotations.Parameter; 7 | import io.swagger.v3.oas.annotations.enums.ParameterIn; 8 | import io.swagger.v3.oas.annotations.media.Schema; 9 | import io.swagger.v3.oas.annotations.responses.ApiResponse; 10 | import io.swagger.v3.oas.annotations.security.SecurityRequirement; 11 | import io.swagger.v3.oas.annotations.tags.Tag; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | 15 | import java.util.List; 16 | 17 | @Tag(name = "Permission Management related to JWT", description = "APIs for managing permissions to access resources using JWT Permissions based on roles") 18 | @SecurityRequirement(name = "bearerAuth") 19 | public interface IPermissionJwtController { 20 | 21 | @Operation(summary = "Get user permissions", description = "Retrieves all permissions for the current user") 22 | @ApiResponse(responseCode = "200", description = "Permissions retrieved successfully") 23 | @ApiResponse(responseCode = "404", description = "The user has no permissions") 24 | @Parameter( 25 | name = "Accept-Language", 26 | in = ParameterIn.HEADER, 27 | required = true, 28 | description = "Language code (e.g., 'en' for English, 'es' for Spanish)", 29 | example = "en", 30 | schema = @Schema(type = "string", defaultValue = "en") 31 | ) 32 | @GetMapping("/user/permissions") 33 | ResponseEntity>> getCurrentUserPermissions(); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/user/IUserController.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.controller.api.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.common.response.ApiResponseDataPojo; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserProfileDTO; 5 | import io.swagger.v3.oas.annotations.Operation; 6 | import io.swagger.v3.oas.annotations.Parameter; 7 | import io.swagger.v3.oas.annotations.enums.ParameterIn; 8 | import io.swagger.v3.oas.annotations.media.Schema; 9 | import io.swagger.v3.oas.annotations.responses.ApiResponse; 10 | import io.swagger.v3.oas.annotations.security.SecurityRequirement; 11 | import io.swagger.v3.oas.annotations.tags.Tag; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | 16 | @Tag(name = "User Management", description = "APIs for managing users") 17 | @SecurityRequirement(name = "bearerAuth") 18 | public interface IUserController { 19 | 20 | @Operation(summary = "Get user profile", description = "Retrieves user profile by ID") 21 | @ApiResponse(responseCode = "200", description = "Profile found") 22 | @ApiResponse(responseCode = "404", description = "User not found") 23 | @Parameter(name = "Accept-Language", in = ParameterIn.HEADER, required = true, description = "Language code (e.g., 'en' for English, 'es' for Spanish)", example = "en", schema = @Schema(type = "string", defaultValue = "en")) 24 | @GetMapping("/{id}/profile") 25 | ResponseEntity> getUserProfile( 26 | @Parameter(description = "User ID") @PathVariable Integer id); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/user/developer/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains controllers for managing developer users. 3 | * Includes CRUD operations and developer-specific functionality. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.controller.api.user.developer; 6 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/user/impl/UserControllerImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.controller.api.user.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.controller.api.user.IUserController; 4 | import com.spacecodee.springbootsecurityopentemplate.controller.base.AbstractController; 5 | import com.spacecodee.springbootsecurityopentemplate.data.common.response.ApiResponseDataPojo; 6 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserProfileDTO; 7 | import com.spacecodee.springbootsecurityopentemplate.language.MessageParameterHandler; 8 | import com.spacecodee.springbootsecurityopentemplate.service.user.IUserService; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | @Slf4j 16 | @RestController 17 | @RequestMapping("/user/security") 18 | public class UserControllerImpl extends AbstractController implements IUserController { 19 | 20 | private final IUserService userService; 21 | 22 | public UserControllerImpl(MessageParameterHandler messageParameterHandler, IUserService userService) { 23 | super(messageParameterHandler); 24 | this.userService = userService; 25 | } 26 | 27 | @Override 28 | public ResponseEntity> getUserProfile(Integer id) { 29 | UserProfileDTO userProfile = this.userService.getUserProfile(id); 30 | return ResponseEntity.ok(super.createDataResponse( 31 | userProfile, 32 | "user.profile.found.success", 33 | HttpStatus.OK, 34 | userProfile.getUsername())); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/api/user/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Root package for user management controllers. 3 | * Contains sub-packages for different user types (admin, developer, 4 | * technician). 5 | */ 6 | package com.spacecodee.springbootsecurityopentemplate.controller.api.user; 7 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/base/AbstractController.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.controller.base; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.common.response.ApiResponseDataPojo; 4 | import com.spacecodee.springbootsecurityopentemplate.data.common.response.ApiResponsePojo; 5 | import com.spacecodee.springbootsecurityopentemplate.language.MessageParameterHandler; 6 | import jakarta.validation.Valid; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.http.HttpStatus; 10 | 11 | @RequiredArgsConstructor 12 | @Slf4j 13 | public abstract class AbstractController { 14 | 15 | protected final MessageParameterHandler messageParameterHandler; 16 | 17 | protected ApiResponsePojo createResponse(String messageKey, HttpStatus status) { 18 | return ApiResponsePojo.of( 19 | this.messageParameterHandler.createMessage(messageKey), 20 | status); 21 | } 22 | 23 | protected ApiResponsePojo createResponse(String messageKey, HttpStatus status, Object... params) { 24 | return ApiResponsePojo.of( 25 | this.messageParameterHandler.createMessage(messageKey, params), status); 26 | } 27 | 28 | protected ApiResponseDataPojo createDataResponse(@Valid T data, String messageKey, HttpStatus status) { 29 | return ApiResponseDataPojo.of( 30 | this.messageParameterHandler.createMessage(messageKey), 31 | status, 32 | data); 33 | } 34 | 35 | protected ApiResponseDataPojo createDataResponse(@Valid T data, String messageKey, HttpStatus status, Object... params) { 36 | return ApiResponseDataPojo.of( 37 | this.messageParameterHandler.createMessage(messageKey, params), 38 | status, 39 | data); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/controller/base/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains base classes and abstractions for controllers. 3 | * Provides common functionality and utilities used across all controllers. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.controller.base; 6 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/base/IJwtTokenFields.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.base; 2 | 3 | import java.util.Date; 4 | 5 | public interface IJwtTokenFields { 6 | String getToken(); 7 | 8 | Date getExpiryDate(); 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/auth/AuthenticationResponsePojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.auth; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.ToString; 7 | 8 | import java.io.Serial; 9 | import java.io.Serializable; 10 | 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Data 14 | @ToString 15 | public class AuthenticationResponsePojo implements Serializable { 16 | @Serial 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String jwt; 20 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/response/ApiErrorDataPojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.response; 2 | 3 | import lombok.Getter; 4 | import org.jetbrains.annotations.Contract; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | @Getter 8 | public final class ApiErrorDataPojo extends ApiErrorPojo { 9 | private final transient E data; 10 | 11 | private ApiErrorDataPojo(String backendMessage, String message, String path, String method, E data) { 12 | super(backendMessage, message, path, method); 13 | this.data = data; 14 | } 15 | 16 | @Contract("_, _, _, _, _ -> new") 17 | public static @NotNull ApiErrorDataPojo of( 18 | String backendMessage, String message, String path, String method, E data) { 19 | return new ApiErrorDataPojo<>(backendMessage, message, path, method, data); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/response/ApiErrorPojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.response; 2 | 3 | import lombok.Getter; 4 | import org.jetbrains.annotations.Contract; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | @Getter 8 | public non-sealed class ApiErrorPojo extends BaseResponsePojo { 9 | private final String backendMessage; 10 | private final String message; 11 | private final String path; 12 | private final String method; 13 | 14 | protected ApiErrorPojo(String backendMessage, String message, String path, String method) { 15 | super(); 16 | this.backendMessage = backendMessage; 17 | this.message = message; 18 | this.path = path; 19 | this.method = method; 20 | } 21 | 22 | @Contract("_, _, _, _ -> new") 23 | public static @NotNull ApiErrorPojo of(String backendMessage, String message, String path, String method) { 24 | return new ApiErrorPojo(backendMessage, message, path, method); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/response/ApiResponseDataPojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.response; 2 | 3 | import lombok.Getter; 4 | import org.jetbrains.annotations.Contract; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.http.HttpStatus; 7 | 8 | @Getter 9 | public final class ApiResponseDataPojo extends ApiResponsePojo { 10 | private final T data; 11 | 12 | private ApiResponseDataPojo(String message, HttpStatus httpStatus, T data) { 13 | super(message, httpStatus); 14 | this.data = data; 15 | } 16 | 17 | @Contract("_, _, _ -> new") 18 | public static @NotNull ApiResponseDataPojo of(String message, HttpStatus status, T data) { 19 | return new ApiResponseDataPojo<>(message, status, data); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/response/ApiResponsePojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.response; 2 | 3 | import lombok.Getter; 4 | import org.jetbrains.annotations.Contract; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.http.HttpStatus; 7 | 8 | @Getter 9 | public non-sealed class ApiResponsePojo extends BaseResponsePojo { 10 | private final String message; 11 | private final HttpStatus httpStatus; 12 | 13 | protected ApiResponsePojo(String message, HttpStatus httpStatus) { 14 | super(); 15 | this.message = message; 16 | this.httpStatus = httpStatus; 17 | } 18 | 19 | @Contract("_, _ -> new") 20 | public static @NotNull ApiResponsePojo of(String message, HttpStatus status) { 21 | return new ApiResponsePojo(message, status); 22 | } 23 | 24 | public int getStatus() { 25 | return httpStatus.value(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/common/response/BaseResponsePojo.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.common.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.Getter; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | @Getter 10 | public abstract sealed class BaseResponsePojo implements Serializable 11 | permits ApiResponsePojo, ApiErrorPojo { 12 | 13 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 14 | private final LocalDateTime timestamp; 15 | 16 | protected BaseResponsePojo() { 17 | this.timestamp = LocalDateTime.now(); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/auth/AuthResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.auth; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | import java.time.Instant; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class AuthResponseDTO { 11 | 12 | private String token; 13 | 14 | private Instant expiresAt; 15 | 16 | private String tokenType = "Bearer"; 17 | 18 | private String username; 19 | 20 | private String role; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/auth/JwtTokenDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.auth; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.spacecodee.springbootsecurityopentemplate.data.base.IJwtTokenFields; 5 | import jakarta.validation.constraints.NotNull; 6 | 7 | import java.io.Serializable; 8 | import java.util.Date; 9 | 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public record JwtTokenDTO(Integer id, @NotNull String token, @NotNull Boolean isValid, 12 | @NotNull Date expiryDate) implements IJwtTokenFields, Serializable { 13 | @Override 14 | public String getToken() { 15 | return this.token; 16 | } 17 | 18 | @Override 19 | public Date getExpiryDate() { 20 | return this.expiryDate; 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/auth/SecurityJwtTokenDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.auth; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.ToString; 7 | 8 | import java.util.Date; 9 | 10 | import com.spacecodee.springbootsecurityopentemplate.data.base.IJwtTokenFields; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Data 15 | @ToString 16 | public class SecurityJwtTokenDTO implements IJwtTokenFields { 17 | 18 | private int id; 19 | private String token; 20 | private Date expiryDate; 21 | private boolean isValid; 22 | private int userDetailsId; 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/base/BaseAuditDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.base; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.Instant; 7 | 8 | @Getter 9 | @Setter 10 | public abstract class BaseAuditDTO { 11 | 12 | protected Instant createdAt; 13 | 14 | protected Instant updatedAt; 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/module/ModuleDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.module; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class ModuleDTO { 9 | 10 | private Integer id; 11 | 12 | private String name; 13 | 14 | private String basePath; 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/operation/OperationDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.operation; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class OperationDTO { 9 | 10 | private Integer id; 11 | 12 | private String tag; 13 | 14 | private String path; 15 | 16 | private String httpMethod; 17 | 18 | private Boolean permitAll; 19 | 20 | private Integer moduleId; 21 | 22 | private String moduleName; 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/operation/OperationDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.operation; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class OperationDetailDTO extends OperationDTO { 11 | 12 | private String moduleBasePath; 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/permission/PermissionDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.permission; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class PermissionDTO { 9 | 10 | private Integer id; 11 | 12 | private Integer roleId; 13 | 14 | private Integer operationId; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/permission/PermissionDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.permission; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class PermissionDetailDTO extends PermissionDTO { 11 | 12 | private String roleName; 13 | 14 | private String operationTag; 15 | 16 | private String operationPath; 17 | 18 | private String operationHttpMethod; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/role/RoleDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.role; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class RoleDTO { 9 | 10 | private Integer id; 11 | 12 | private String name; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/core/role/RoleDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.core.role; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Set; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @NoArgsConstructor 12 | public class RoleDetailDTO extends RoleDTO { 13 | 14 | private Set permissions; 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/JwtTokenSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | import java.time.Instant; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class JwtTokenSecurityDTO { 11 | 12 | private int id; 13 | 14 | private String token; 15 | 16 | private Instant expiryDate; 17 | 18 | private boolean isValid; 19 | 20 | private UserSecurityDTO userSecurityDTO; 21 | 22 | private String jti; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/ModuleSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class ModuleSecurityDTO { 9 | 10 | private int id; 11 | 12 | private String name; 13 | 14 | private String basePath; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/OperationSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class OperationSecurityDTO { 9 | 10 | private int id; 11 | 12 | private String tag; 13 | 14 | private String path; 15 | 16 | private String httpMethod; 17 | 18 | private boolean permitAll; 19 | 20 | private ModuleSecurityDTO moduleSecurityDTO; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/OperationSecurityPathDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import lombok.Data; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @Data 7 | @RequiredArgsConstructor 8 | public class OperationSecurityPathDTO { 9 | 10 | String fullPath; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/PermissionSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class PermissionSecurityDTO { 9 | 10 | private int id; 11 | 12 | private OperationSecurityDTO operationDTO; 13 | 14 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/RoleSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.RoleEnum; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class RoleSecurityDTO { 12 | 13 | private int id; 14 | 15 | private RoleEnum name; 16 | 17 | private List permissionDTOList; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/security/UserSecurityDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.security; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collection; 12 | import java.util.Collections; 13 | 14 | 15 | @Data 16 | @NoArgsConstructor 17 | public class UserSecurityDTO implements UserDetails { 18 | 19 | private long id; 20 | 21 | private String name; 22 | 23 | private String username; 24 | 25 | @JsonIgnore 26 | private String password; 27 | 28 | private transient RoleSecurityDTO roleSecurityDTO; 29 | 30 | @Override 31 | public Collection getAuthorities() { 32 | if (this.roleSecurityDTO == null) 33 | return Collections.emptyList(); 34 | 35 | return new ArrayList<>(this.roleSecurityDTO.getPermissionDTOList() 36 | .stream() 37 | .map(each -> each.getOperationDTO().getTag()) 38 | .map(SimpleGrantedAuthority::new) 39 | .toList()); 40 | } 41 | 42 | @JsonIgnore 43 | @Override 44 | public boolean isAccountNonExpired() { 45 | return true; 46 | } 47 | 48 | @JsonIgnore 49 | @Override 50 | public boolean isAccountNonLocked() { 51 | return true; 52 | } 53 | 54 | @JsonIgnore 55 | @Override 56 | public boolean isCredentialsNonExpired() { 57 | return true; 58 | } 59 | 60 | @JsonIgnore 61 | @Override 62 | public boolean isEnabled() { 63 | return true; 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class UserDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/UserDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class UserDetailDTO extends UserDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/UserProfileDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.RoleEnum; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import lombok.experimental.Accessors; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Accessors(chain = true) 13 | public class UserProfileDTO { 14 | 15 | private Integer id; 16 | 17 | private String username; 18 | 19 | private String firstName; 20 | 21 | private String lastName; 22 | 23 | private String email; 24 | 25 | private String phoneNumber; 26 | 27 | private String profilePicturePath; 28 | 29 | private Boolean status; 30 | 31 | private RoleEnum role; 32 | 33 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/developer/DeveloperDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.developer; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class DeveloperDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/developer/DeveloperDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.developer; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class DeveloperDetailDTO extends DeveloperDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/editor/EditorDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.editor; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class EditorDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/editor/EditorDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.editor; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class EditorDetailDTO extends EditorDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/guest/GuestDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.guest; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class GuestDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/guest/GuestDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.guest; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class GuestDetailDTO extends GuestDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/manager/ManagerDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.manager; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class ManagerDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/manager/ManagerDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.manager; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class ManagerDetailDTO extends ManagerDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/system/admin/SystemAdminDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.system.admin; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class SystemAdminDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/system/admin/SystemAdminDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.system.admin; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class SystemAdminDetailDTO extends SystemAdminDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/viewer/ViewerDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.viewer; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @Data 7 | @NoArgsConstructor 8 | public class ViewerDTO { 9 | 10 | private Integer id; 11 | 12 | private String username; 13 | 14 | private String firstName; 15 | 16 | private String lastName; 17 | 18 | private String email; 19 | 20 | private String phoneNumber; 21 | 22 | private String profilePicturePath; 23 | 24 | private Boolean status; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/dto/user/viewer/ViewerDetailDTO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.dto.user.viewer; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.NoArgsConstructor; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | @Data 9 | @NoArgsConstructor 10 | public class ViewerDetailDTO extends ViewerDTO { 11 | 12 | private Integer roleId; 13 | 14 | private String roleName; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/record/TokenClaims.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.record; 2 | 3 | import java.util.Map; 4 | 5 | public record TokenClaims( 6 | String subject, 7 | Map claims) { 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/record/TokenEvent.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.record; 2 | 3 | public record TokenEvent( 4 | String token, 5 | String operation, 6 | String reason 7 | ) { 8 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/record/TokenStateChangeEvent.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.record; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.TokenStateEnum; 4 | 5 | public record TokenStateChangeEvent( 6 | String token, 7 | TokenStateEnum state, 8 | String reason 9 | ) { 10 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/record/TokenValidationResult.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.record; 2 | 3 | public record TokenValidationResult( 4 | String token, 5 | boolean wasRefreshed) { 6 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/auth/LoginVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.auth; 2 | 3 | import jakarta.validation.constraints.NotEmpty; 4 | import jakarta.validation.constraints.Pattern; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class LoginVO { 11 | 12 | @NotEmpty(message = "{validation.login.username.required}") 13 | @Pattern(regexp = "^\\w+$", message = "{validation.login.username.pattern}") 14 | private String username; 15 | 16 | @NotEmpty(message = "{validation.login.password.required}") 17 | private String password; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/module/CreateModuleVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.module; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Size; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class CreateModuleVO { 12 | @NotBlank(message = "{module.name.required}") 13 | @Size(max = 100, message = "{module.name.max.length}") 14 | @Pattern(regexp = "^[A-Za-z_]+$", message = "{module.name.pattern}") 15 | private String name; 16 | 17 | @NotBlank(message = "{module.base.path.required}") 18 | @Size(max = 100, message = "{module.base.path.max.length}") 19 | @Pattern(regexp = "^/[a-zA-Z-]+(?:/[a-zA-Z-]+)*+$", message = "{module.base.path.pattern}") 20 | private String basePath; 21 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/module/ModuleFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.module; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class ModuleFilterVO { 12 | 13 | @Pattern(regexp = "^[a-zA-Z_]*$", message = "{module.name.pattern}") 14 | private String name; 15 | 16 | @Pattern(regexp = "^/[a-zA-Z-]+(?:/[a-zA-Z-]+)*+$", message = "{module.base.path.pattern}") 17 | private String basePath; 18 | 19 | @Min(value = 0, message = "{module.page.min}") 20 | private Integer page = 0; 21 | 22 | @Min(value = 1, message = "{module.size.min}") 23 | @Max(value = 100, message = "{module.size.max}") 24 | private Integer size = 10; 25 | 26 | @Pattern(regexp = "^(name|basePath)$", message = "{module.sort.invalid}") 27 | private String sortBy = "name"; 28 | 29 | @Pattern(regexp = "^(ASC|DESC)$", message = "{module.sort.direction.invalid}") 30 | private String sortDirection = "ASC"; 31 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/module/UpdateModuleVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.module; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Size; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateModuleVO { 12 | private Integer id; 13 | 14 | @NotBlank(message = "{module.name.required}") 15 | @Size(max = 100, message = "{module.name.max.length}") 16 | @Pattern(regexp = "^[A-Za-z_]+$", message = "{module.name.pattern}") 17 | private String name; 18 | 19 | @NotBlank(message = "{module.base.path.required}") 20 | @Size(max = 100, message = "{module.base.path.max.length}") 21 | @Pattern(regexp = "^/[a-zA-Z-]+(?:/[a-zA-Z-]+)*+$", message = "{module.base.path.pattern}") 22 | private String basePath; 23 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/operation/CreateOperationVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation; 2 | 3 | import jakarta.validation.constraints.*; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | public class CreateOperationVO { 10 | @NotBlank(message = "{operation.tag.required}") 11 | @Size(max = 100, message = "{operation.tag.max.length}") 12 | private String tag; 13 | 14 | @Size(max = 50, message = "{operation.path.max.length}") 15 | private String path = ""; 16 | 17 | @NotBlank(message = "{operation.http.method.required}") 18 | @Size(max = 10, message = "{operation.http.method.max.length}") 19 | @Pattern(regexp = "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$", 20 | message = "{operation.http.method.pattern}") 21 | private String httpMethod; 22 | 23 | @Pattern(regexp = "^(true|false)$", message = "{operation.permit.all.pattern}", flags = Pattern.Flag.CASE_INSENSITIVE) 24 | private String permitAll = "false"; 25 | 26 | @NotNull(message = "{operation.module.required}") 27 | @Min(value = 1, message = "{operation.filter.module.id.min}") 28 | private Integer moduleId; 29 | 30 | public Boolean getPermitAll() { 31 | return Boolean.parseBoolean(permitAll); 32 | } 33 | 34 | public void setPermitAll(Boolean permitAll) { 35 | this.permitAll = permitAll != null ? permitAll.toString() : "false"; 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/operation/OperationFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class OperationFilterVO { 12 | 13 | @Pattern(regexp = "^[a-zA-Z_]*$", message = "{operation.filter.tag.pattern}") 14 | private String tag; 15 | 16 | @Pattern(regexp = "^$|^/[a-zA-Z-]+(?:/[a-zA-Z-]+)*+$", message = "{operation.filter.path.pattern}") 17 | private String path; 18 | 19 | @Pattern(regexp = "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$", message = "{operation.http.method.pattern}", flags = Pattern.Flag.CASE_INSENSITIVE) 20 | private String httpMethod; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{operation.filter.permit.all.pattern}", flags = Pattern.Flag.CASE_INSENSITIVE) 23 | private String permitAll; 24 | 25 | @Min(value = 1, message = "{operation.filter.module.id.min}") 26 | private Integer moduleId; 27 | 28 | @Min(value = 0, message = "{operation.page.min}") 29 | private Integer page = 0; 30 | 31 | @Min(value = 1, message = "{operation.size.min}") 32 | @Max(value = 100, message = "{operation.size.max}") 33 | private Integer size = 10; 34 | 35 | @Pattern(regexp = "^(tag|path|httpMethod)$", message = "{operation.sort.invalid}") 36 | private String sortBy = "tag"; 37 | 38 | @Pattern(regexp = "^(ASC|DESC)$", message = "{operation.sort.direction.invalid}") 39 | private String sortDirection = "ASC"; 40 | 41 | public Boolean getPermitAll() { 42 | return permitAll != null ? Boolean.parseBoolean(permitAll) : null; 43 | } 44 | 45 | public void setPermitAll(Boolean permitAll) { 46 | this.permitAll = permitAll != null ? permitAll.toString() : null; 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/operation/UpdateOperationVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation; 2 | 3 | import jakarta.validation.constraints.*; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | public class UpdateOperationVO { 10 | 11 | private Integer id; 12 | 13 | @NotBlank(message = "{operation.tag.required}") 14 | @Size(max = 100, message = "{operation.tag.max.length}") 15 | private String tag; 16 | 17 | @Size(max = 50, message = "{operation.path.max.length}") 18 | private String path = ""; 19 | 20 | @NotBlank(message = "{operation.http.method.required}") 21 | @Size(max = 10, message = "{operation.http.method.max.length}") 22 | private String httpMethod; 23 | 24 | @Pattern(regexp = "^(true|false)$", message = "{operation.permit.all.pattern}", flags = Pattern.Flag.CASE_INSENSITIVE) 25 | private String permitAll = "false"; 26 | 27 | @NotNull(message = "{operation.module.required}") 28 | @Min(value = 1, message = "{operation.filter.module.id.min}") 29 | private Integer moduleId; 30 | 31 | public Boolean getPermitAll() { 32 | return Boolean.parseBoolean(permitAll); 33 | } 34 | 35 | public void setPermitAll(Boolean permitAll) { 36 | this.permitAll = permitAll != null ? permitAll.toString() : "false"; 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/permission/CreatePermissionVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission; 2 | 3 | import jakarta.validation.constraints.Min; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class CreatePermissionVO { 11 | 12 | @NotNull(message = "{permission.role.id.required}") 13 | @Min(value = 1, message = "{permission.role.id.min}") 14 | private Integer roleId; 15 | 16 | @NotNull(message = "{permission.operation.id.required}") 17 | @Min(value = 1, message = "{permission.operation.id.min}") 18 | private Integer operationId; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/permission/PermissionFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class PermissionFilterVO { 12 | 13 | @Min(value = 1, message = "{permission.filter.role.id.min}") 14 | private Integer roleId; 15 | 16 | @Min(value = 1, message = "{permission.filter.operation.id.min}") 17 | private Integer operationId; 18 | 19 | @Min(value = 0, message = "{permission.page.min}") 20 | private Integer page = 0; 21 | 22 | @Min(value = 1, message = "{permission.size.min}") 23 | @Max(value = 100, message = "{permission.size.max}") 24 | private Integer size = 10; 25 | 26 | @Pattern(regexp = "^(roleId|operationId)$", message = "{permission.sort.invalid}") 27 | private String sortBy = "roleId"; 28 | 29 | @Pattern(regexp = "^(ASC|DESC)$", message = "{permission.sort.direction.invalid}") 30 | private String sortDirection = "ASC"; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/permission/UpdatePermissionVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission; 2 | 3 | import jakarta.validation.constraints.Min; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | public class UpdatePermissionVO { 11 | 12 | @NotNull(message = "{permission.id.required}") 13 | private Integer id; 14 | 15 | @NotNull(message = "{permission.role.id.required}") 16 | @Min(value = 1, message = "{permission.role.id.min}") 17 | private Integer roleId; 18 | 19 | @NotNull(message = "{permission.operation.id.required}") 20 | @Min(value = 1, message = "{permission.operation.id.min}") 21 | private Integer operationId; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/role/CreateRoleVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.role; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Set; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | public class CreateRoleVO { 14 | 15 | @NotBlank(message = "{role.name.required}") 16 | @Size(max = 20, message = "{role.name.max.length}") 17 | @Pattern(regexp = "^[A-Z_]*$", message = "{role.name.pattern}") 18 | private String name; 19 | 20 | private Set permissionIds; 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/role/RoleFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.role; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class RoleFilterVO { 12 | 13 | @Pattern(regexp = "^[A-Z_]*$", message = "{role.filter.name.pattern}") 14 | private String name; 15 | 16 | @Min(value = 0, message = "{role.page.min}") 17 | private Integer page = 0; 18 | 19 | @Min(value = 1, message = "{role.size.min}") 20 | @Max(value = 100, message = "{role.size.max}") 21 | private Integer size = 10; 22 | 23 | @Pattern(regexp = "^(name)$", message = "{role.sort.invalid}") 24 | private String sortBy = "name"; 25 | 26 | @Pattern(regexp = "^(ASC|DESC)$", message = "{role.sort.direction.invalid}") 27 | private String sortDirection = "ASC"; 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/core/role/UpdateRoleVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.core.role; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Size; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Set; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | public class UpdateRoleVO { 14 | 15 | private Integer id; 16 | 17 | @NotBlank(message = "{role.name.required}") 18 | @Size(max = 20, message = "{role.name.max.length}") 19 | @Pattern(regexp = "^[A-Z_]*$", message = "{role.name.pattern}") 20 | private String name; 21 | 22 | private Set permissionIds; 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/jwt/CreateJwtTokenVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.jwt; 2 | 3 | import jakarta.validation.constraints.*; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.time.Instant; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class CreateJwtTokenVO { 12 | 13 | @NotBlank(message = "{validation.jwt.token.required}") 14 | private String token; 15 | 16 | @NotNull(message = "{validation.jwt.valid.required}") 17 | private Boolean valid; 18 | 19 | @NotNull(message = "{validation.jwt.expiry.required}") 20 | @Future(message = "{validation.jwt.expiry.future}") 21 | private Instant expiryDate; 22 | 23 | @NotNull(message = "{validation.jwt.user.required}") 24 | @Min(value = 1, message = "{validation.jwt.user.id.min}") 25 | private Integer userId; 26 | 27 | @NotNull(message = "{validation.jwt.state.required}") 28 | private String state; 29 | 30 | private Boolean isRevoked = false; 31 | private Instant revokedAt; 32 | 33 | @Size(max = 255, message = "{validation.jwt.revoked.reason.max}") 34 | private String revokedReason; 35 | 36 | @Min(value = 0, message = "{validation.jwt.refresh.count.min}") 37 | private Integer refreshCount = 0; 38 | private Instant lastRefreshAt; 39 | private String previousToken; 40 | 41 | @NotNull(message = "{validation.jwt.usage.count.min}") 42 | @Min(value = 0, message = "{validation.jwt.usage.count.min}") 43 | private Integer usageCount = 0; 44 | 45 | private Instant lastAccessAt; 46 | 47 | @Size(max = 100, message = "{validation.jwt.last.operation.max}") 48 | private String lastOperation; 49 | 50 | @NotBlank(message = "{validation.jwt.jti.required}") 51 | private String jti; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/jwt/UpdateJwtTokenVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.jwt; 2 | 3 | import jakarta.validation.constraints.*; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.time.Instant; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateJwtTokenVO { 12 | 13 | @Min(value = 1, message = "{validation.jwt.id.min}") 14 | private int id; 15 | 16 | @NotBlank(message = "{validation.jwt.token.required}") 17 | private String token; 18 | 19 | @NotNull(message = "{validation.jwt.valid.required}") 20 | private Boolean valid; 21 | 22 | @NotNull(message = "{validation.jwt.expiry.required}") 23 | @Future(message = "{validation.jwt.expiry.future}") 24 | private Instant expiryDate; 25 | 26 | @NotNull(message = "{validation.jwt.user.required}") 27 | @Min(value = 1, message = "{validation.jwt.user.id.min}") 28 | private Integer userId; 29 | 30 | @NotNull(message = "{validation.jwt.state.required}") 31 | private String state; 32 | 33 | private Boolean isRevoked = false; 34 | private Instant revokedAt; 35 | 36 | @Size(max = 255, message = "{validation.jwt.revoked.reason.max}") 37 | private String revokedReason; 38 | 39 | @Min(value = 0, message = "{validation.jwt.refresh.count.min}") 40 | private Integer refreshCount = 0; 41 | private Instant lastRefreshAt; 42 | private String previousToken; 43 | 44 | @NotNull(message = "{validation.jwt.usage.count.min}") 45 | @Min(value = 0, message = "{validation.jwt.usage.count.min}") 46 | private Integer usageCount = 0; 47 | 48 | private Instant lastAccessAt; 49 | 50 | @Size(max = 100, message = "{validation.jwt.last.operation.max}") 51 | private String lastOperation; 52 | 53 | @NotBlank(message = "{validation.jwt.jti.required}") 54 | private String jti; 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/developer/DeveloperFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.developer; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class DeveloperFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{developer.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{developer.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{developer.filter.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{developer.filter.enabled.pattern}", 23 | flags = Pattern.Flag.CASE_INSENSITIVE) 24 | private String enabled; 25 | 26 | @Min(value = 0, message = "{developer.page.min}") 27 | private Integer page = 0; 28 | 29 | @Min(value = 1, message = "{developer.size.min}") 30 | @Max(value = 100, message = "{developer.size.max}") 31 | private Integer size = 10; 32 | 33 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{developer.sort.invalid}") 34 | private String sortBy = "username"; 35 | 36 | @Pattern(regexp = "^(ASC|DESC)$", message = "{developer.sort.direction.invalid}") 37 | private String sortDirection = "ASC"; 38 | 39 | public Boolean getEnabled() { 40 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/developer/UpdateDeveloperVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.developer; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateDeveloperVO { 12 | 13 | private Integer id; 14 | 15 | @NotBlank(message = "{developer.firstname.required}") 16 | @Size(max = 20, message = "{developer.firstname.size}") 17 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{developer.firstname.pattern}") 18 | private String firstName; 19 | 20 | @NotBlank(message = "{developer.lastname.required}") 21 | @Size(max = 20, message = "{developer.lastname.size}") 22 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{developer.lastname.pattern}") 23 | private String lastName; 24 | 25 | @Pattern(regexp = "^9\\d{8}$", message = "{developer.phone.pattern}") 26 | private String phoneNumber; 27 | 28 | @Size(max = 255, message = "{developer.profile.picture.size}") 29 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", message = "{developer.profile.picture.pattern}") 30 | private String profilePicturePath; 31 | 32 | @Pattern(regexp = "^(true|false)$", message = "{developer.status.pattern}") 33 | private String status; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/editor/EditorFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.editor; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class EditorFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{editor.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{editor.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{editor.filter.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{editor.filter.enabled.pattern}", 23 | flags = Pattern.Flag.CASE_INSENSITIVE) 24 | private String enabled; 25 | 26 | @Min(value = 0, message = "{editor.page.min}") 27 | private Integer page = 0; 28 | 29 | @Min(value = 1, message = "{editor.size.min}") 30 | @Max(value = 100, message = "{editor.size.max}") 31 | private Integer size = 10; 32 | 33 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{editor.sort.invalid}") 34 | private String sortBy = "username"; 35 | 36 | @Pattern(regexp = "^(ASC|DESC)$", message = "{editor.sort.direction.invalid}") 37 | private String sortDirection = "ASC"; 38 | 39 | public Boolean getEnabled() { 40 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/editor/UpdateEditorVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.editor; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateEditorVO { 12 | 13 | private Integer id; 14 | 15 | @NotBlank(message = "{editor.firstname.required}") 16 | @Size(max = 20, message = "{editor.firstname.size}") 17 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{editor.firstname.pattern}") 18 | private String firstName; 19 | 20 | @NotBlank(message = "{editor.lastname.required}") 21 | @Size(max = 20, message = "{editor.lastname.size}") 22 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{editor.lastname.pattern}") 23 | private String lastName; 24 | 25 | @Pattern(regexp = "^9\\d{8}$", message = "{editor.phone.pattern}") 26 | private String phoneNumber; 27 | 28 | @Size(max = 255, message = "{editor.profile.picture.size}") 29 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", 30 | message = "{editor.profile.picture.pattern}") 31 | private String profilePicturePath; 32 | 33 | @Pattern(regexp = "^(true|false)$", message = "{editor.status.pattern}") 34 | private String status; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/guest/GuestFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.guest; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class GuestFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{guest.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{guest.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{guest.filter.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{guest.filter.enabled.pattern}", 23 | flags = Pattern.Flag.CASE_INSENSITIVE) 24 | private String enabled; 25 | 26 | @Min(value = 0, message = "{guest.page.min}") 27 | private Integer page = 0; 28 | 29 | @Min(value = 1, message = "{guest.size.min}") 30 | @Max(value = 100, message = "{guest.size.max}") 31 | private Integer size = 10; 32 | 33 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{guest.sort.invalid}") 34 | private String sortBy = "username"; 35 | 36 | @Pattern(regexp = "^(ASC|DESC)$", message = "{guest.sort.direction.invalid}") 37 | private String sortDirection = "ASC"; 38 | 39 | public Boolean getEnabled() { 40 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/guest/UpdateGuestVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.guest; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateGuestVO { 12 | 13 | private Integer id; 14 | 15 | @NotBlank(message = "{guest.firstname.required}") 16 | @Size(max = 20, message = "{guest.firstname.size}") 17 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{guest.firstname.pattern}") 18 | private String firstName; 19 | 20 | @NotBlank(message = "{guest.lastname.required}") 21 | @Size(max = 20, message = "{guest.lastname.size}") 22 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{guest.lastname.pattern}") 23 | private String lastName; 24 | 25 | @Pattern(regexp = "^9\\d{8}$", message = "{guest.phone.pattern}") 26 | private String phoneNumber; 27 | 28 | @Size(max = 255, message = "{guest.profile.picture.size}") 29 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", 30 | message = "{guest.profile.picture.pattern}") 31 | private String profilePicturePath; 32 | 33 | @Pattern(regexp = "^(true|false)$", message = "{guest.status.pattern}") 34 | private String status; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/manager/ManagerFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.manager; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class ManagerFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{manager.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{manager.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{manager.filter.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{manager.filter.enabled.pattern}", 23 | flags = Pattern.Flag.CASE_INSENSITIVE) 24 | private String enabled; 25 | 26 | @Min(value = 0, message = "{manager.page.min}") 27 | private Integer page = 0; 28 | 29 | @Min(value = 1, message = "{manager.size.min}") 30 | @Max(value = 100, message = "{manager.size.max}") 31 | private Integer size = 10; 32 | 33 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{manager.sort.invalid}") 34 | private String sortBy = "username"; 35 | 36 | @Pattern(regexp = "^(ASC|DESC)$", message = "{manager.sort.direction.invalid}") 37 | private String sortDirection = "ASC"; 38 | 39 | public Boolean getEnabled() { 40 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/manager/UpdateManagerVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.manager; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateManagerVO { 12 | 13 | private Integer id; 14 | 15 | @NotBlank(message = "{manager.firstname.required}") 16 | @Size(max = 20, message = "{manager.firstname.size}") 17 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{manager.firstname.pattern}") 18 | private String firstName; 19 | 20 | @NotBlank(message = "{manager.lastname.required}") 21 | @Size(max = 20, message = "{manager.lastname.size}") 22 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{manager.lastname.pattern}") 23 | private String lastName; 24 | 25 | @Pattern(regexp = "^9\\d{8}$", message = "{manager.phone.pattern}") 26 | private String phoneNumber; 27 | 28 | @Size(max = 255, message = "{manager.profile.picture.size}") 29 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", 30 | message = "{manager.profile.picture.pattern}") 31 | private String profilePicturePath; 32 | 33 | @Pattern(regexp = "^(true|false)$", message = "{manager.status.pattern}") 34 | private String status; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/system/admin/SystemAdminFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.system.admin; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class SystemAdminFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{system.admin.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{system.admin.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{system.admin.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Pattern(regexp = "^(true|false)$", message = "{system.admin.filter.enabled.pattern}", flags = Pattern.Flag.CASE_INSENSITIVE) 23 | private String enabled; 24 | 25 | @Min(value = 0, message = "{system.admin.page.min}") 26 | private Integer page = 0; 27 | 28 | @Min(value = 1, message = "{system.admin.size.min}") 29 | @Max(value = 100, message = "{system.admin.size.max}") 30 | private Integer size = 10; 31 | 32 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{system.admin.sort.invalid}") 33 | private String sortBy = "username"; 34 | 35 | @Pattern(regexp = "^(ASC|DESC)$", message = "{system.admin.sort.direction.invalid}") 36 | private String sortDirection = "ASC"; 37 | 38 | public Boolean getEnabled() { 39 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/system/admin/UpdateSystemAdminVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.system.admin; 2 | 3 | import jakarta.validation.constraints.*; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | public class UpdateSystemAdminVO { 10 | 11 | private Integer id; 12 | 13 | @NotBlank(message = "{system.admin.firstname.required}") 14 | @Size(max = 20, message = "{system.admin.firstname.size}") 15 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{system.admin.firstname.pattern}") 16 | private String firstName; 17 | 18 | @NotBlank(message = "{system.admin.lastname.required}") 19 | @Size(max = 20, message = "{system.admin.lastname.size}") 20 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{system.admin.lastname.pattern}") 21 | private String lastName; 22 | 23 | @Pattern(regexp = "^9\\d{8}$", message = "{system.admin.phone.pattern}") 24 | private String phoneNumber; 25 | 26 | @Size(max = 255, message = "{system.admin.profile.picture.size}") 27 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", message = "{system.admin.profile.picture.pattern}") 28 | private String profilePicturePath; 29 | 30 | @Pattern(regexp = "^(true|false)$", message = "{system.admin.status.pattern}") 31 | private String status; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/viewer/UpdateViewerVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.viewer; 2 | 3 | import jakarta.validation.constraints.NotBlank; 4 | import jakarta.validation.constraints.Pattern; 5 | import jakarta.validation.constraints.Size; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class UpdateViewerVO { 12 | 13 | private Integer id; 14 | 15 | @NotBlank(message = "{viewer.firstname.required}") 16 | @Size(max = 20, message = "{viewer.firstname.size}") 17 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{viewer.firstname.pattern}") 18 | private String firstName; 19 | 20 | @NotBlank(message = "{viewer.lastname.required}") 21 | @Size(max = 20, message = "{viewer.lastname.size}") 22 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{viewer.lastname.pattern}") 23 | private String lastName; 24 | 25 | @Pattern(regexp = "^9\\d{8}$", message = "{viewer.phone.pattern}") 26 | private String phoneNumber; 27 | 28 | @Size(max = 255, message = "{viewer.profile.picture.size}") 29 | @Pattern(regexp = "^https?://[\\w.-]+\\.\\w{2,6}/[\\w/-]+\\.(jpg|jpeg|png)$", 30 | message = "{viewer.profile.picture.pattern}") 31 | private String profilePicturePath; 32 | 33 | @Pattern(regexp = "^(true|false)$", message = "{viewer.status.pattern}") 34 | private String status; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/data/vo/user/viewer/ViewerFilterVO.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.data.vo.user.viewer; 2 | 3 | import jakarta.validation.constraints.Max; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.Pattern; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | public class ViewerFilterVO { 12 | 13 | @Pattern(regexp = "^\\w*$", message = "{viewer.filter.username.pattern}") 14 | private String username; 15 | 16 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{viewer.filter.name.pattern}") 17 | private String firstName; 18 | 19 | @Pattern(regexp = "^[a-zA-Z\\s]*$", message = "{viewer.filter.lastname.pattern}") 20 | private String lastName; 21 | 22 | @Min(value = 1, message = "{viewer.filter.role.id.min}") 23 | private Integer roleId; 24 | 25 | @Pattern(regexp = "^(true|false)$", message = "{viewer.filter.enabled.pattern}", 26 | flags = Pattern.Flag.CASE_INSENSITIVE) 27 | private String enabled; 28 | 29 | @Min(value = 0, message = "{viewer.page.min}") 30 | private Integer page = 0; 31 | 32 | @Min(value = 1, message = "{viewer.size.min}") 33 | @Max(value = 100, message = "{viewer.size.max}") 34 | private Integer size = 10; 35 | 36 | @Pattern(regexp = "^(username|firstName|lastName)$", message = "{viewer.sort.invalid}") 37 | private String sortBy = "username"; 38 | 39 | @Pattern(regexp = "^(ASC|DESC)$", message = "{viewer.sort.direction.invalid}") 40 | private String sortDirection = "ASC"; 41 | 42 | public Boolean getEnabled() { 43 | return enabled != null ? Boolean.parseBoolean(enabled) : null; 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/enums/PasswordValidationRule.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.enums; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum PasswordValidationRule { 7 | MIN_LENGTH(8), 8 | MAX_LENGTH(32), 9 | MIN_SPECIAL_CHARS(1), 10 | MIN_DIGITS(1), 11 | MIN_UPPERCASE(1), 12 | MIN_LOWERCASE(1); 13 | 14 | private final int value; 15 | 16 | PasswordValidationRule(int value) { 17 | this.value = value; 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/enums/TokenStateEnum.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.enums; 2 | 3 | public enum TokenStateEnum { 4 | 5 | CREATED, 6 | ACTIVE, 7 | REFRESHED, 8 | EXPIRED, 9 | REVOKED, 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/AccessDeniedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class AccessDeniedException extends BaseException { 6 | 7 | public AccessDeniedException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/InvalidCredentialsException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class InvalidCredentialsException extends BaseException { 6 | 7 | public InvalidCredentialsException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/InvalidPasswordComplexityException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.web.bind.annotation.ResponseStatus; 8 | 9 | import java.util.List; 10 | 11 | @Slf4j 12 | @ResponseStatus(HttpStatus.BAD_REQUEST) 13 | public class InvalidPasswordComplexityException extends BaseException { 14 | 15 | public InvalidPasswordComplexityException(List messages, String locale) { 16 | super(String.join("|", messages), locale); 17 | log.debug("Creating exception with messages: {}", messages); 18 | } 19 | 20 | public InvalidPasswordComplexityException(String messageKey, String locale) { 21 | super(messageKey, locale); 22 | log.debug("Creating exception with message key: {}", messageKey); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/InvalidPasswordException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ResponseStatus; 6 | 7 | import java.util.List; 8 | 9 | @ResponseStatus(HttpStatus.BAD_REQUEST) 10 | public class InvalidPasswordException extends BaseException { 11 | 12 | public InvalidPasswordException(List messages, String locale) { 13 | super(String.join(" ", messages), locale); 14 | } 15 | 16 | public InvalidPasswordException(String message, String locale) { 17 | super(message, locale); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class UnauthorizedException extends BaseException { 6 | 7 | public UnauthorizedException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenAuthenticationException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenAuthenticationException extends BaseException { 6 | 7 | public JwtTokenAuthenticationException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenClaimsInvalidException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenClaimsInvalidException extends BaseException { 6 | 7 | public JwtTokenClaimsInvalidException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenClaimsInvalidException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenClaimsMissingException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenClaimsMissingException extends BaseException { 6 | 7 | public JwtTokenClaimsMissingException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenClaimsMissingException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenException extends BaseException { 6 | 7 | public JwtTokenException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenExpiredException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenExpiredException extends BaseException { 6 | 7 | public JwtTokenExpiredException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenExpiredException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenHeaderAlgException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenHeaderAlgException extends BaseException { 6 | 7 | public JwtTokenHeaderAlgException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenHeaderAlgException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenHeaderDecodeException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenHeaderDecodeException extends BaseException { 6 | 7 | public JwtTokenHeaderDecodeException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenHeaderFormatException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenHeaderFormatException extends BaseException { 6 | 7 | public JwtTokenHeaderFormatException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenHeaderTypeException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenHeaderTypeException extends BaseException { 6 | 7 | public JwtTokenHeaderTypeException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenHeaderValidationException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenHeaderValidationException extends BaseException { 6 | 7 | public JwtTokenHeaderValidationException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenInvalidException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenInvalidException extends BaseException { 6 | 7 | public JwtTokenInvalidException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenInvalidException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenInvalidFormatException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenInvalidFormatException extends BaseException { 6 | 7 | public JwtTokenInvalidFormatException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenInvalidSignatureException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenInvalidSignatureException extends BaseException { 6 | 7 | public JwtTokenInvalidSignatureException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenMalformedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenMalformedException extends BaseException { 6 | 7 | public JwtTokenMalformedException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenMissingClaimException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenMissingClaimException extends BaseException { 6 | 7 | public JwtTokenMissingClaimException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenNotFoundException extends BaseException { 6 | 7 | public JwtTokenNotFoundException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenSignatureException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenSignatureException extends BaseException { 6 | 7 | public JwtTokenSignatureException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenUnexpectedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenUnexpectedException extends BaseException { 6 | 7 | public JwtTokenUnexpectedException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public JwtTokenUnexpectedException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/jwt/JwtTokenValidationException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class JwtTokenValidationException extends BaseException { 6 | 7 | public JwtTokenValidationException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains authentication related exceptions. 3 | * All exceptions in this package extend BusinessException and handle 4 | * authentication specific error cases like invalid credentials, token issues, 5 | * etc. 6 | */ 7 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/ratelimit/RateLimitExceededException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.ratelimit; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ResponseStatus; 6 | 7 | @ResponseStatus(HttpStatus.TOO_MANY_REQUESTS) 8 | public class RateLimitExceededException extends BaseException { 9 | 10 | public RateLimitExceededException(String messageKey, String locale) { 11 | super(messageKey, locale); 12 | } 13 | 14 | public RateLimitExceededException(String messageKey, String locale, Object... args) { 15 | super(messageKey, locale, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/auth/ratelimit/RateLimitException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.auth.ratelimit; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class RateLimitException extends BaseException { 6 | 7 | public RateLimitException(String messageKey, String locale, Object... args) { 8 | super(messageKey, locale, args); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/base/BaseException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.base; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public abstract class BaseException extends RuntimeException { 7 | 8 | private final String messageKey; 9 | private final String locale; 10 | private final transient Object[] parameters; 11 | 12 | protected BaseException(String messageKey, String locale, Object... parameters) { 13 | super(messageKey); 14 | this.messageKey = messageKey; 15 | this.locale = locale; 16 | this.parameters = parameters; 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/endpoint/ModuleNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.endpoint; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class ModuleNotFoundException extends BaseException { 6 | public ModuleNotFoundException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/endpoint/OperationNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.endpoint; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class OperationNotFoundException extends BaseException { 6 | public OperationNotFoundException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/endpoint/PermissionNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.endpoint; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class PermissionNotFoundException extends BaseException { 6 | public PermissionNotFoundException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | 10 | public PermissionNotFoundException(String messageKey, String locale, Object... parameters) { 11 | super(messageKey, locale, parameters); 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/endpoint/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains endpoint management related exceptions. 3 | * Handles errors related to modules, operations, and permissions management. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.exceptions.endpoint; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/locale/LocaleResolutionException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.locale; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class LocaleResolutionException extends BaseException { 6 | 7 | public LocaleResolutionException(String messageKey, String locale, Object... parameters) { 8 | super(messageKey, locale, parameters); 9 | } 10 | 11 | public LocaleResolutionException(String messageKey, String locale) { 12 | super(messageKey, locale); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/CannotSaveException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class CannotSaveException extends BaseException { 6 | public CannotSaveException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/NoContentException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class NoContentException extends BaseException { 6 | public NoContentException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/NoCreatedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class NoCreatedException extends BaseException { 6 | 7 | public NoCreatedException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public NoCreatedException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/NoDeletedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class NoDeletedException extends BaseException { 6 | 7 | public NoDeletedException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public NoDeletedException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/NoDisabledException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class NoDisabledException extends BaseException { 6 | public NoDisabledException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/NoUpdatedException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class NoUpdatedException extends BaseException { 6 | 7 | public NoUpdatedException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public NoUpdatedException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/operation/package-info.java: -------------------------------------------------------------------------------- 1 | // package-info.java 2 | /** 3 | * Contains CRUD operation related exceptions. 4 | * Handles errors during create, read, update and delete operations. 5 | */ 6 | package com.spacecodee.springbootsecurityopentemplate.exceptions.operation; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/LastAdminException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class LastAdminException extends BaseException { 6 | public LastAdminException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/LastClientException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class LastClientException extends BaseException { 6 | public LastClientException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/LastDeveloperException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class LastDeveloperException extends BaseException { 6 | public LastDeveloperException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/LastTechnicianException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class LastTechnicianException extends BaseException { 6 | public LastTechnicianException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/RoleNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class RoleNotFoundException extends BaseException { 6 | public RoleNotFoundException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class UserNotFoundException extends BaseException { 6 | 7 | public UserNotFoundException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public UserNotFoundException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/UsernameAlreadyExistsException.java: -------------------------------------------------------------------------------- 1 | // UsernameAlreadyExistsException.java 2 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 3 | 4 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 5 | 6 | public class UsernameAlreadyExistsException extends BaseException { 7 | public UsernameAlreadyExistsException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/UsernameNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class UsernameNotFoundException extends BaseException { 6 | public UsernameNotFoundException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/user/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains user management related exceptions. 3 | * Handles errors related to user operations like not found, duplicates, etc. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.exceptions.user; 6 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/AlreadyExistsException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class AlreadyExistsException extends BaseException { 6 | 7 | public AlreadyExistsException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public AlreadyExistsException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/DoNotExistsByIdException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class DoNotExistsByIdException extends BaseException { 6 | 7 | public DoNotExistsByIdException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/IllegalArgumentException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class IllegalArgumentException extends BaseException { 6 | 7 | public IllegalArgumentException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public IllegalArgumentException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/InvalidParameterException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class InvalidParameterException extends BaseException { 6 | 7 | public InvalidParameterException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public InvalidParameterException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/ObjectNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class ObjectNotFoundException extends BaseException { 6 | 7 | public ObjectNotFoundException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | 11 | public ObjectNotFoundException(String messageKey, String locale, Object... parameters) { 12 | super(messageKey, locale, parameters); 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/PasswordDoNotMatchException.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 4 | 5 | public class PasswordDoNotMatchException extends BaseException { 6 | public PasswordDoNotMatchException(String messageKey, String locale) { 7 | super(messageKey, locale); 8 | } 9 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/ValidationException.java: -------------------------------------------------------------------------------- 1 | // ValidationException.java 2 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 3 | 4 | import com.spacecodee.springbootsecurityopentemplate.exceptions.base.BaseException; 5 | 6 | public class ValidationException extends BaseException { 7 | public ValidationException(String messageKey, String locale) { 8 | super(messageKey, locale); 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/exceptions/validation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains validation related exceptions. 3 | * Handles input validation errors, parameter validation, and password 4 | * validation. 5 | */ 6 | package com.spacecodee.springbootsecurityopentemplate.exceptions.validation; 7 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/language/MessageConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.language; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.language.constant.LanguageConstants; 4 | import org.springframework.context.MessageSource; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.support.ReloadableResourceBundleMessageSource; 8 | 9 | import java.nio.charset.StandardCharsets; 10 | 11 | @Configuration 12 | public class MessageConfig { 13 | 14 | @Bean 15 | public MessageSource messageSource() { 16 | var messageSource = new ReloadableResourceBundleMessageSource(); 17 | messageSource.setBasenames( 18 | LanguageConstants.getMessageSources().toArray(new String[0])); 19 | messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name()); 20 | messageSource.setCacheSeconds(3600); 21 | messageSource.setFallbackToSystemLocale(false); 22 | return messageSource; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/language/MessageParameterHandler.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.language; 2 | 3 | import java.util.Arrays; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.spacecodee.springbootsecurityopentemplate.utils.LocaleUtils; 7 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.MessageParameterUtil; 8 | 9 | import lombok.RequiredArgsConstructor; 10 | import lombok.extern.slf4j.Slf4j; 11 | 12 | @Component 13 | @Slf4j 14 | @RequiredArgsConstructor 15 | public class MessageParameterHandler { 16 | 17 | private final MessageUtilComponent messageUtilComponent; 18 | private final LocaleUtils localeUtils; 19 | 20 | public String createMessage(String messageKey, Object... parameters) { 21 | var locale = localeUtils.getCurrentLocale(); 22 | log.debug("Creating message with key: '{}', locale: '{}', parameters: {}", 23 | messageKey, locale, Arrays.toString(parameters)); 24 | 25 | Object[] validatedParams = MessageParameterUtil.validateAndCleanParams(parameters); 26 | return messageUtilComponent.getMessage(messageKey, locale, validatedParams); 27 | } 28 | 29 | public String createErrorMessage(String messageKey, Object... parameters) { 30 | var locale = localeUtils.getCurrentLocale(); 31 | 32 | log.debug("Creating error message with key: '{}', locale: '{}', parameters: {}", 33 | messageKey, locale, Arrays.toString(parameters)); 34 | 35 | Object[] validatedParams = MessageParameterUtil.validateAndCleanParams(parameters); 36 | return messageUtilComponent.getMessage(messageKey, validatedParams); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/language/MessageResolverService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.language; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.context.MessageSource; 5 | import org.springframework.context.NoSuchMessageException; 6 | import org.springframework.context.i18n.LocaleContextHolder; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | @RequiredArgsConstructor 11 | public class MessageResolverService { 12 | 13 | private final MessageSource messageSource; 14 | 15 | public String resolveMessage(String key, Object... args) { 16 | try { 17 | return messageSource.getMessage(key, args, LocaleContextHolder.getLocale()); 18 | } catch (NoSuchMessageException e) { 19 | return key; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/language/config/LocaleConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.language.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.LocaleResolver; 6 | import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; 7 | 8 | import com.spacecodee.springbootsecurityopentemplate.language.constant.LanguageConstants; 9 | 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import java.util.Locale; 13 | 14 | @Configuration 15 | public class LocaleConfig { 16 | 17 | private static final List SUPPORTED_LOCALES = Arrays.asList( 18 | Locale.forLanguageTag(LanguageConstants.DEFAULT_LOCALE), 19 | Locale.forLanguageTag("es")); 20 | 21 | @Bean 22 | public LocaleResolver localeResolver() { 23 | var resolver = new AcceptHeaderLocaleResolver(); 24 | resolver.setSupportedLocales(LocaleConfig.SUPPORTED_LOCALES); 25 | resolver.setDefaultLocale(Locale.forLanguageTag(LanguageConstants.DEFAULT_LOCALE)); 26 | return resolver; 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/language/constant/LanguageConstants.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.language.constant; 2 | 3 | import java.util.List; 4 | 5 | public final class LanguageConstants { 6 | private LanguageConstants() { 7 | throw new IllegalStateException("Constants class"); 8 | } 9 | 10 | public static final String DEFAULT_LOCALE = "en"; 11 | public static final String ACCEPT_LANGUAGE_HEADER = "Accept-Language"; 12 | 13 | private static final List MESSAGE_SOURCES = List.of( 14 | "classpath:locale/message", 15 | "classpath:validation/validation", 16 | "classpath:api/api-doc"); 17 | 18 | public static List getMessageSources() { 19 | return MESSAGE_SOURCES; 20 | } 21 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/security/IModuleSecurityMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.ModuleSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.ModuleEntity; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 8 | public interface IModuleSecurityMapper { 9 | 10 | @Named("mapModuleIdToModuleEntity") 11 | default ModuleEntity mapModuleIdToModuleEntity(Integer moduleId) { 12 | if (moduleId == null) 13 | return null; 14 | var moduleEntity = new ModuleEntity(); 15 | moduleEntity.setId(moduleId); 16 | return moduleEntity; 17 | } 18 | 19 | @Named("mapModuleEntityToModuleId") 20 | default Integer mapModuleEntityToModuleId(ModuleEntity moduleEntity) { 21 | return moduleEntity != null ? moduleEntity.getId() : null; 22 | } 23 | 24 | @Mapping(target = "id", source = "id") 25 | ModuleSecurityDTO toUserDetailsModuleDTO(ModuleEntity moduleEntity); 26 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/security/IOperationSecurityMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.OperationSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.OperationSecurityPathDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.OperationEntity; 6 | import org.mapstruct.*; 7 | 8 | @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = { 9 | IModuleSecurityMapper.class}) 10 | public interface IOperationSecurityMapper { 11 | 12 | @Mapping(target = "moduleSecurityDTO", source = "moduleEntity") 13 | OperationSecurityDTO toOperationSecurityDTO(OperationEntity operationEntity); 14 | 15 | @Mapping(target = "id", source = "id") 16 | @Mapping(target = "tag", source = "tag") 17 | @Mapping(target = "path", source = "path") 18 | @Mapping(target = "httpMethod", source = "httpMethod") 19 | @Mapping(target = "permitAll", source = "permitAll") 20 | @Mapping(target = "moduleSecurityDTO", ignore = true) 21 | OperationSecurityDTO toOperationSecurityDTO(OperationSecurityDTO operationDTO); 22 | 23 | @Mapping(target = "fullPath", source = ".", qualifiedByName = "buildFullPath") 24 | OperationSecurityPathDTO toOperationSecurityPathDTO(OperationEntity operationEntity); 25 | 26 | @Named("buildFullPath") 27 | default String buildFullPath(OperationEntity operationEntity) { 28 | if (operationEntity == null || operationEntity.getModuleEntity() == null) { 29 | return ""; 30 | } 31 | return operationEntity.getModuleEntity().getBasePath() + operationEntity.getPath(); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/security/IPermissionSecurityMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.PermissionSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.PermissionEntity; 5 | import org.mapstruct.*; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = { 12 | IOperationSecurityMapper.class, IRoleSecurityMapper.class}) 13 | public interface IPermissionSecurityMapper { 14 | 15 | @Named("toUserDetailsPermissionDTOList") 16 | default List toUserDetailsPermissionDTOList(Set permissionEntities) { 17 | if (permissionEntities == null) { 18 | return Collections.emptyList(); 19 | } 20 | return permissionEntities.stream() 21 | .map(this::toBasicUserDetailsPermissionDTO) 22 | .toList(); 23 | } 24 | 25 | @Named("toBasicUserDetailsPermissionDTO") 26 | @Mapping(target = "id", source = "id") 27 | @Mapping(target = "operationDTO", source = "operationEntity") 28 | PermissionSecurityDTO toBasicUserDetailsPermissionDTO(PermissionEntity permissionEntity); 29 | 30 | @Mapping(target = "id", source = "id") 31 | @Mapping(target = "operationDTO", source = "operationEntity") 32 | PermissionSecurityDTO toPermissionSecurityDTO(PermissionEntity permissionEntity); 33 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/security/IRoleSecurityMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.RoleSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.RoleEntity; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = { 8 | IPermissionSecurityMapper.class }) 9 | public interface IRoleSecurityMapper { 10 | 11 | @Mapping(target = "id", source = "id") 12 | @Mapping(target = "name", source = "name") 13 | @Mapping(target = "permissionDTOList", source = "permissionEntities", qualifiedByName = "toUserDetailsPermissionDTOList") 14 | RoleSecurityDTO toRoleSecurityDTO(RoleEntity roleEntity); 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/security/IUserSecurityMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.security; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.UserSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 5 | import org.mapstruct.*; 6 | 7 | @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.IGNORE, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = { 8 | IRoleSecurityMapper.class}) 9 | public interface IUserSecurityMapper { 10 | 11 | @Mapping(target = "id", source = "id") 12 | @Mapping(target = "username", source = "username") 13 | @Mapping(target = "name", source = "firstName") 14 | @Mapping(target = "password", source = "password") 15 | @Mapping(target = "roleSecurityDTO", source = "roleEntity") 16 | UserSecurityDTO toUserSecurityDTO(UserEntity userEntity); 17 | 18 | @Named("mapUserIdToUserEntity") 19 | default UserEntity mapUserIdToUserEntity(int userId) { 20 | var userEntity = new UserEntity(); 21 | userEntity.setId(userId); 22 | return userEntity; 23 | } 24 | 25 | @Named("mapUserIdEntityToUser") 26 | default Integer mapUserIdEntityToUser(UserEntity userEntity) { 27 | return userEntity != null ? userEntity.getId() : null; 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/mappers/user/IUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.mappers.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserProfileDTO; 6 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 7 | import org.mapstruct.*; 8 | 9 | @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING) 10 | public interface IUserMapper { 11 | 12 | UserEntity toEntity(UserDTO viewerDTO); 13 | 14 | UserDTO toDTO(UserEntity userEntity); 15 | 16 | UserDetailDTO toDetailsDTO(UserEntity userEntity); 17 | 18 | @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) 19 | UserEntity partialUpdate(UserDTO viewerDTO, @MappingTarget UserEntity userEntity); 20 | 21 | @Mapping(source = "roleEntity.name", target = "role") 22 | UserProfileDTO toProfileDTO(UserEntity userEntity); 23 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/entity/BaseAuditEntity.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.entity; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.MappedSuperclass; 5 | import jakarta.persistence.PrePersist; 6 | import jakarta.persistence.PreUpdate; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | import java.time.Instant; 11 | 12 | @Getter 13 | @Setter 14 | @MappedSuperclass 15 | public abstract class BaseAuditEntity { 16 | 17 | @Column(name = "created_at", nullable = false, updatable = false) 18 | protected Instant createdAt; 19 | 20 | @Column(name = "updated_at") 21 | protected Instant updatedAt; 22 | 23 | @PrePersist 24 | protected void onCreate() { 25 | createdAt = Instant.now(); 26 | } 27 | 28 | @PreUpdate 29 | protected void onUpdate() { 30 | updatedAt = Instant.now(); 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/entity/ModuleEntity.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.entity; 2 | 3 | import jakarta.persistence.*; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.*; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serial; 9 | import java.io.Serializable; 10 | 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Setter 14 | @Getter 15 | @ToString 16 | @Accessors(chain = true) 17 | @Entity() 18 | @Table(name = "module", schema = "public") 19 | public class ModuleEntity implements Serializable { 20 | 21 | @Serial 22 | private static final long serialVersionUID = -6383996348361015603L; 23 | 24 | @Id 25 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "module_id_gen") 26 | @SequenceGenerator(name = "module_id_gen", sequenceName = "module_id_seq", allocationSize = 1) 27 | @Column(name = "id", nullable = false) 28 | private Integer id; 29 | 30 | @NotNull 31 | @Column(name = "name", nullable = false, length = Integer.MAX_VALUE) 32 | private String name; 33 | 34 | @NotNull 35 | @Column(name = "base_path", nullable = false, length = Integer.MAX_VALUE) 36 | private String basePath; 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/entity/OperationEntity.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.entity; 2 | 3 | import jakarta.persistence.*; 4 | import jakarta.validation.constraints.NotNull; 5 | import lombok.*; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serial; 9 | import java.io.Serializable; 10 | 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | @Accessors(chain = true) 17 | @Entity() 18 | @Table(name = "operation", schema = "public") 19 | public class OperationEntity implements Serializable { 20 | 21 | @Serial 22 | private static final long serialVersionUID = -6157134909667621423L; 23 | 24 | @Id 25 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "operation_id_gen") 26 | @SequenceGenerator(name = "operation_id_gen", sequenceName = "operation_id_seq", allocationSize = 1) 27 | @Column(name = "id", nullable = false) 28 | private Integer id; 29 | 30 | @NotNull 31 | @Column(name = "tag", nullable = false, length = Integer.MAX_VALUE) 32 | private String tag; 33 | 34 | @NotNull 35 | @Column(name = "path", nullable = false, length = Integer.MAX_VALUE) 36 | private String path; 37 | 38 | @NotNull 39 | @Column(name = "http_method", nullable = false, length = Integer.MAX_VALUE) 40 | private String httpMethod; 41 | 42 | @NotNull 43 | @Column(name = "permit_all", nullable = false) 44 | private Boolean permitAll = false; 45 | 46 | @NotNull 47 | @ManyToOne 48 | @JoinColumn(name = "module_id", referencedColumnName = "id", nullable = false) 49 | private ModuleEntity moduleEntity; 50 | 51 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/entity/PermissionEntity.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.*; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.*; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Setter 15 | @Getter 16 | @ToString 17 | @Accessors(chain = true) 18 | @Entity() 19 | @Table(name = "permission", schema = "public") 20 | public class PermissionEntity implements Serializable { 21 | 22 | @Serial 23 | private static final long serialVersionUID = -1389093610467033486L; 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "permission_id_gen") 27 | @SequenceGenerator(name = "permission_id_gen", sequenceName = "permission_id_seq", allocationSize = 1) 28 | @Column(name = "id", nullable = false) 29 | private Integer id; 30 | 31 | @Column(name = "role_id", insertable = false, updatable = false) 32 | private Integer roleId; 33 | 34 | @Column(name = "operation_id", insertable = false, updatable = false) 35 | private Integer operationId; 36 | 37 | @JsonIgnore 38 | @ManyToOne 39 | @JoinColumn(name = "role_id", nullable = false) 40 | private RoleEntity roleEntity; 41 | 42 | @NotNull 43 | @ManyToOne(fetch = FetchType.LAZY, optional = false) 44 | @JoinColumn(name = "operation_id", nullable = false) 45 | @ToString.Exclude 46 | private OperationEntity operationEntity; 47 | 48 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/entity/RoleEntity.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.entity; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.RoleEnum; 4 | import jakarta.persistence.*; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.*; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Setter 17 | @Getter 18 | @ToString 19 | @Accessors(chain = true) 20 | @Entity() 21 | @Table(name = "role", schema = "public") 22 | public class RoleEntity implements Serializable { 23 | 24 | @Serial 25 | private static final long serialVersionUID = -4118972354508428674L; 26 | @Id 27 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "role_id_gen") 28 | @SequenceGenerator(name = "role_id_gen", sequenceName = "role_id_seq", allocationSize = 1) 29 | @Column(name = "id", nullable = false) 30 | private Integer id; 31 | 32 | @NotNull 33 | @Enumerated(EnumType.STRING) 34 | @Column(name = "name", nullable = false, length = 20) 35 | private RoleEnum name; 36 | 37 | @OneToMany(mappedBy = "roleEntity", fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = PermissionEntity.class) 38 | @ToString.Exclude 39 | private Set permissionEntities = new HashSet<>(); 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/core/IModuleRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.core; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.ModuleEntity; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.stereotype.Repository; 10 | 11 | @Repository 12 | public interface IModuleRepository extends JpaRepository { 13 | 14 | @Query("SELECT m FROM ModuleEntity m WHERE " + 15 | "(:name IS NULL OR m.name ILIKE %:name%) AND " + 16 | "(:basePath IS NULL OR m.basePath ILIKE %:basePath%)") 17 | Page findByFilters( 18 | @Param("name") String name, 19 | @Param("basePath") String basePath, 20 | Pageable pageable); 21 | 22 | boolean existsByNameIgnoreCase(String name); 23 | 24 | boolean existsByNameIgnoreCaseAndIdNot(String name, Integer id); 25 | 26 | boolean existsByBasePathIgnoreCase(String basePath); 27 | 28 | boolean existsByBasePathIgnoreCaseAndIdNot(String basePath, Integer id); 29 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/core/IRoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.core; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.RoleEnum; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.RoleEntity; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.data.repository.query.Param; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import java.util.Optional; 13 | 14 | @Repository 15 | public interface IRoleRepository extends JpaRepository { 16 | 17 | @Query("SELECT r FROM RoleEntity r WHERE " + 18 | "(:name IS NULL OR UPPER(CAST(r.name AS string)) ILIKE %:name%)") 19 | Page findByFilters( 20 | @Param("name") String name, 21 | Pageable pageable); 22 | 23 | @Query("SELECT r FROM RoleEntity r WHERE r.name = :name") 24 | Optional findByName(@Param("name") RoleEnum name); 25 | 26 | @Query("SELECT CASE WHEN COUNT(r) > 0 THEN true ELSE false END FROM RoleEntity r " + 27 | "WHERE r.name = :name") 28 | boolean existsByName(@Param("name") RoleEnum name); 29 | 30 | @Query("SELECT CASE WHEN COUNT(r) > 0 THEN true ELSE false END FROM RoleEntity r " + 31 | "WHERE r.name = :name AND r.id <> :id") 32 | boolean existsByNameAndIdNot( 33 | @Param("name") RoleEnum name, 34 | @Param("id") Integer id); 35 | 36 | // Get admin role from properties 37 | @Query("SELECT r FROM RoleEntity r WHERE r.name = :roleName") 38 | Optional findAdminRole(@Param("roleName") RoleEnum roleName); 39 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/security/jwt/IJwtTokenSecurityRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.security.jwt; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.JwtTokenEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.time.Instant; 11 | import java.util.List; 12 | import java.util.Optional; 13 | 14 | @Repository 15 | public interface IJwtTokenSecurityRepository extends JpaRepository { 16 | 17 | Optional findByToken(String token); 18 | 19 | @Modifying 20 | @Query("DELETE FROM JwtTokenEntity t WHERE t.token = :token") 21 | void deleteByToken(@Param("token") String token); 22 | 23 | @Modifying 24 | @Query("DELETE FROM JwtTokenEntity t WHERE t.expiryDate < :now") 25 | int deleteExpiredTokens(@Param("now") Instant now); 26 | 27 | @Modifying 28 | @Query("DELETE FROM JwtTokenEntity t WHERE t.isRevoked = true") 29 | int deleteRevokedTokens(); 30 | 31 | @Modifying 32 | @Query("DELETE FROM JwtTokenEntity t WHERE t.lastAccessAt < :threshold") 33 | int deleteInactiveTokens(@Param("threshold") Instant threshold); 34 | 35 | @Modifying 36 | @Query("DELETE FROM JwtTokenEntity t WHERE t.state = 'BLACKLISTED'") 37 | int deleteBlacklistedTokens(); 38 | 39 | @Query("SELECT t FROM JwtTokenEntity t WHERE t.expiryDate < :now AND t.isRevoked = false") 40 | List findExpiredTokens(@Param("now") Instant now); 41 | 42 | List findAllByUserEntity_Username(String username); 43 | 44 | Optional findFirstByUserEntity_UsernameOrderByCreatedAtDesc(String username); 45 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/security/operation/IOperationSecurityRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.security.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.OperationEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | @Repository 11 | public interface IOperationSecurityRepository extends JpaRepository { 12 | 13 | @Query("SELECT o FROM OperationEntity o JOIN FETCH o.moduleEntity WHERE o.permitAll = true") 14 | List findByPermitAllIsPublic(); 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/security/user/IUserSecurityRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.security.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface IUserSecurityRepository extends JpaRepository { 11 | 12 | Optional findByUsername(String username); 13 | 14 | boolean existsByUsername(String username); 15 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/user/IEditorRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.stereotype.Repository; 10 | 11 | @Repository 12 | public interface IEditorRepository extends JpaRepository { 13 | 14 | boolean existsByUsername(String username); 15 | 16 | @Query("SELECT COUNT(u) > 0 FROM UserEntity u WHERE u.username = :username AND u.roleEntity.id = :roleId") 17 | boolean existsByUsernameAndRoleId(@Param("username") String username, @Param("roleId") Integer roleId); 18 | 19 | boolean existsByEmail(String email); 20 | 21 | @Query("SELECT COUNT(u) > 0 FROM UserEntity u WHERE u.email = :email AND u.roleEntity.id = :roleId") 22 | boolean existsByEmailAndRoleId(@Param("email") String email, @Param("roleId") Integer roleId); 23 | 24 | @Query(""" 25 | SELECT u FROM UserEntity u 26 | WHERE (:username IS NULL OR u.username LIKE %:username%) 27 | AND (:firstName IS NULL OR u.firstName LIKE %:firstName%) 28 | AND (:lastName IS NULL OR u.lastName LIKE %:lastName%) 29 | AND u.roleEntity.id = :roleId 30 | AND (:status IS NULL OR u.status = :status) 31 | """) 32 | Page searchEditors( 33 | @Param("username") String username, 34 | @Param("firstName") String firstName, 35 | @Param("lastName") String lastName, 36 | @Param("roleId") Integer roleId, 37 | @Param("status") Boolean status, 38 | Pageable pageable); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/user/IGuestRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Query; 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.stereotype.Repository; 10 | 11 | @Repository 12 | public interface IGuestRepository extends JpaRepository { 13 | 14 | boolean existsByUsername(String username); 15 | 16 | @Query("SELECT COUNT(u) > 0 FROM UserEntity u WHERE u.username = :username AND u.roleEntity.id = :roleId") 17 | boolean existsByUsernameAndRoleId(@Param("username") String username, @Param("roleId") Integer roleId); 18 | 19 | boolean existsByEmail(String email); 20 | 21 | @Query("SELECT COUNT(u) > 0 FROM UserEntity u WHERE u.email = :email AND u.roleEntity.id = :roleId") 22 | boolean existsByEmailAndRoleId(@Param("email") String email, @Param("roleId") Integer roleId); 23 | 24 | @Query(""" 25 | SELECT u FROM UserEntity u 26 | WHERE (:username IS NULL OR u.username LIKE %:username%) 27 | AND (:firstName IS NULL OR u.firstName LIKE %:firstName%) 28 | AND (:lastName IS NULL OR u.lastName LIKE %:lastName%) 29 | AND u.roleEntity.id = :roleId 30 | AND (:status IS NULL OR u.status = :status) 31 | """) 32 | Page searchGuests( 33 | @Param("username") String username, 34 | @Param("firstName") String firstName, 35 | @Param("lastName") String lastName, 36 | @Param("roleId") Integer roleId, 37 | @Param("status") Boolean status, 38 | Pageable pageable); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/persistence/repository/user/IUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.persistence.repository.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface IUserRepository extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.cors.CorsConfiguration; 7 | import org.springframework.web.cors.CorsConfigurationSource; 8 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 9 | 10 | import java.util.List; 11 | 12 | @Configuration 13 | public class CorsConfig { 14 | 15 | @Value("${security.cors.allowed-origins}") 16 | private List allowedOrigins; 17 | 18 | @Value("${security.cors.allowed-methods}") 19 | private List allowedMethods; 20 | 21 | @Value("${security.cors.allowed-headers}") 22 | private List allowedHeaders; 23 | 24 | @Bean 25 | CorsConfigurationSource corsConfigurationSource() { 26 | CorsConfiguration configuration = new CorsConfiguration(); 27 | configuration.setAllowedOrigins(allowedOrigins); 28 | configuration.setAllowedMethods(allowedMethods); 29 | configuration.setAllowedHeaders(allowedHeaders); 30 | configuration.setAllowCredentials(true); 31 | configuration.setMaxAge(3600L); 32 | 33 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 34 | source.registerCorsConfiguration("/**", configuration); 35 | return source; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/config/CustomSecurityHeadersConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.config; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.springframework.security.config.Customizer; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; 7 | import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class CustomSecurityHeadersConfigurer 12 | extends AbstractHttpConfigurer { 13 | 14 | @Override 15 | public void configure(@NotNull HttpSecurity http) throws Exception { 16 | Customizer> headersCustomizer = headers -> headers 17 | .contentSecurityPolicy(csp -> csp 18 | .policyDirectives("default-src 'none';")) // Strict CSP for API 19 | .frameOptions(HeadersConfigurer.FrameOptionsConfig::deny) 20 | .httpStrictTransportSecurity(hsts -> hsts 21 | .includeSubDomains(true) 22 | .maxAgeInSeconds(31536000)); 23 | 24 | http.headers(headersCustomizer); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/config/MethodSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.config; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.security.authorization.evaluator.CustomPermissionEvaluator; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; 8 | import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; 9 | import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; 10 | 11 | @Configuration 12 | @EnableMethodSecurity 13 | @RequiredArgsConstructor 14 | public class MethodSecurityConfig { 15 | 16 | private final CustomPermissionEvaluator customPermissionEvaluator; 17 | 18 | @Bean 19 | public MethodSecurityExpressionHandler methodSecurityExpressionHandler() { 20 | var expressionHandler = new DefaultMethodSecurityExpressionHandler(); 21 | expressionHandler.setPermissionEvaluator(this.customPermissionEvaluator); 22 | return expressionHandler; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/config/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | @Configuration 9 | public class PasswordEncoderConfig { 10 | 11 | @Bean 12 | public PasswordEncoder passwordEncoder() { 13 | return new BCryptPasswordEncoder(); 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/handler/CustomAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.handler; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.facade.TokenOperationsFacade; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletResponse; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Slf4j 14 | @Component 15 | @RequiredArgsConstructor 16 | public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { 17 | 18 | private final TokenOperationsFacade tokenOperationsFacade; 19 | 20 | @Override 21 | public void onAuthenticationSuccess(HttpServletRequest request, 22 | HttpServletResponse response, 23 | @NotNull Authentication authentication) { 24 | log.info("User {} successfully authenticated", authentication.getName()); 25 | 26 | // If using form login, extract and activate the token 27 | try { 28 | String token = this.tokenOperationsFacade.extractJwtFromRequest(request); 29 | if (token != null && !token.isEmpty()) { 30 | this.tokenOperationsFacade.activateToken(token); 31 | } 32 | } catch (Exception e) { 33 | log.debug("No token to activate during form authentication: {}", e.getMessage()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/path/ISecurityPathService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.path; 2 | 3 | import jakarta.servlet.http.HttpServletRequest; 4 | 5 | public interface ISecurityPathService { 6 | 7 | boolean isPublicPath(String path); 8 | 9 | boolean isSwaggerPath(String path); 10 | 11 | boolean shouldNotFilter(HttpServletRequest request); 12 | 13 | boolean isErrorPath(String path); 14 | 15 | boolean isRefreshTokenPath(String path); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/security/util/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.security.util; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 4 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.IJwtProviderService; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import lombok.RequiredArgsConstructor; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Slf4j 13 | @Component 14 | @RequiredArgsConstructor 15 | public class SecurityUtils { 16 | 17 | private final IJwtProviderService jwtProviderService; 18 | 19 | private final ExceptionShortComponent exceptionShortComponent; 20 | 21 | private final HttpServletRequest httpServletRequest; 22 | 23 | public Integer getCurrentUserId() { 24 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 25 | if (authentication == null || !authentication.isAuthenticated()) { 26 | throw this.exceptionShortComponent.unauthorizedException("auth.request.null"); 27 | } 28 | 29 | try { 30 | String token = this.jwtProviderService.extractJwtFromRequest(this.httpServletRequest); 31 | return this.jwtProviderService.extractUserId(token); 32 | } catch (Exception e) { 33 | log.error("Error getting current user ID", e); 34 | throw this.exceptionShortComponent.tokenInvalidException("auth.token.userid.invalid"); 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/core/module/IModuleService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.core.module; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.module.ModuleDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.module.CreateModuleVO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.module.ModuleFilterVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.module.UpdateModuleVO; 7 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.ModuleEntity; 8 | import org.springframework.data.domain.Page; 9 | 10 | import java.util.List; 11 | 12 | public interface IModuleService { 13 | 14 | ModuleDTO createModule(CreateModuleVO createModuleVO); 15 | 16 | ModuleDTO updateModule(UpdateModuleVO updateModuleVO); 17 | 18 | ModuleDTO getModuleById(Integer id); 19 | 20 | ModuleEntity getModuleEntityById(Integer id); 21 | 22 | Page searchModules(ModuleFilterVO filterVO); 23 | 24 | List getAllModules(); 25 | 26 | void deleteModule(Integer id); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/core/operation/IOperationService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.core.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.operation.OperationDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.operation.OperationDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation.CreateOperationVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation.OperationFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.operation.UpdateOperationVO; 8 | import org.springframework.data.domain.Page; 9 | 10 | import java.util.List; 11 | 12 | public interface IOperationService { 13 | 14 | OperationDTO createOperation(CreateOperationVO createOperationVO); 15 | 16 | OperationDTO updateOperation(UpdateOperationVO updateOperationVO); 17 | 18 | OperationDTO getOperationById(Integer id); 19 | 20 | OperationDetailDTO getOperationDetailById(Integer id); 21 | 22 | Page searchOperations(OperationFilterVO filterVO); 23 | 24 | List getAllOperationsByModuleId(Integer moduleId); 25 | 26 | List getAllOperations(); 27 | 28 | void deleteOperation(Integer id); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Core business logic services that implement the main functionality of the application. 3 | * Contains user management, endpoint management, and other core features. 4 | */ 5 | package com.spacecodee.springbootsecurityopentemplate.service.core; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/core/permission/IPermissionService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.core.permission; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.permission.PermissionDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.permission.PermissionDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission.CreatePermissionVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission.PermissionFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.permission.UpdatePermissionVO; 8 | import org.springframework.data.domain.Page; 9 | 10 | import java.util.List; 11 | 12 | public interface IPermissionService { 13 | 14 | PermissionDTO createPermission(CreatePermissionVO createPermissionVO); 15 | 16 | PermissionDTO updatePermission(UpdatePermissionVO updatePermissionVO); 17 | 18 | PermissionDTO getPermissionById(Integer id); 19 | 20 | PermissionDetailDTO getPermissionDetailById(Integer id); 21 | 22 | Page searchPermissions(PermissionFilterVO filterVO); 23 | 24 | List getAllPermissionsByRoleId(Integer roleId); 25 | 26 | List getAllPermissionDetailsByRoleId(Integer roleId); 27 | 28 | List getAllPermissions(); 29 | 30 | void deletePermission(Integer id); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/core/role/IRoleService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.core.role; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.role.RoleDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.core.role.RoleDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.role.CreateRoleVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.role.RoleFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.core.role.UpdateRoleVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.RoleEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | import java.util.List; 12 | 13 | public interface IRoleService { 14 | 15 | RoleDTO createRole(CreateRoleVO createRoleVO); 16 | 17 | RoleDTO updateRole(UpdateRoleVO updateRoleVO); 18 | 19 | RoleDTO getRoleById(Integer id); 20 | 21 | RoleDetailDTO getRoleDetailById(Integer id); 22 | 23 | Page searchRoles(RoleFilterVO filterVO); 24 | 25 | List getAllRoles(); 26 | 27 | void deleteRole(Integer id); 28 | 29 | RoleEntity findByName(String roleName); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/auth/IAuthService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.auth; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import com.spacecodee.springbootsecurityopentemplate.data.dto.auth.AuthResponseDTO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.auth.LoginVO; 7 | import jakarta.servlet.http.HttpServletRequest; 8 | import jakarta.validation.Valid; 9 | 10 | public interface IAuthService { 11 | 12 | AuthResponseDTO login(@Valid LoginVO loginVO); 13 | 14 | AuthResponseDTO refreshToken(@NotNull String token); 15 | 16 | void logout(HttpServletRequest request); 17 | 18 | boolean validateToken(String token); 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/operation/IOperationSecurityService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.operation; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.OperationSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.OperationSecurityPathDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.UserSecurityDTO; 6 | 7 | import java.util.List; 8 | 9 | public interface IOperationSecurityService { 10 | 11 | List findByPublicAccess(); 12 | 13 | /** 14 | * Extracts operation security DTOs from a user's security details 15 | * 16 | * @param userSecurityDTO The user security details 17 | * @return List of operation security DTOs 18 | */ 19 | List extractUserOperations(UserSecurityDTO userSecurityDTO); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Security-related services handling JWT tokens, authentication, and authorization. 3 | */ 4 | package com.spacecodee.springbootsecurityopentemplate.service.security; -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/IJwtProviderService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.UserSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.record.TokenClaims; 5 | import io.jsonwebtoken.Claims; 6 | import jakarta.servlet.http.HttpServletRequest; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.time.Instant; 11 | import java.util.Map; 12 | 13 | public interface IJwtProviderService { 14 | 15 | String generateToken(UserDetails user, Map extraClaims); 16 | 17 | Map generateExtraClaims(UserSecurityDTO userDetails); 18 | 19 | String buildToken(@NotNull TokenClaims tokenClaims); 20 | 21 | String extractUsername(String jwt); 22 | 23 | Integer extractUserId(String jwt); 24 | 25 | String extractJwtFromRequest(HttpServletRequest request); 26 | 27 | Instant extractExpiration(String jwt); 28 | 29 | Claims extractClaims(String jwt); 30 | 31 | Claims extractClaimsWithoutValidation(String jwt); 32 | 33 | boolean isTokenValid(String jwt); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/IJwtTokenSecurityService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.UserSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.vo.jwt.UpdateJwtTokenVO; 5 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.JwtTokenEntity; 6 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 7 | 8 | public interface IJwtTokenSecurityService { 9 | 10 | void updateTokenToRefresh(UpdateJwtTokenVO token); 11 | 12 | JwtTokenEntity findByToken(String token); 13 | 14 | JwtTokenEntity handleExistingToken(String username, boolean includeExpired); 15 | 16 | JwtTokenEntity createNewTokenInLogin(UserSecurityDTO userSecurityDTO, UserEntity user); 17 | 18 | JwtTokenEntity refreshExistingTokenOnLogin(UserSecurityDTO userDetails, JwtTokenEntity existingToken); 19 | 20 | int revokeAllUserTokens(String username, String reason); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/builder/ITokenBuilderService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.builder; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.record.TokenClaims; 4 | 5 | import javax.crypto.SecretKey; 6 | 7 | public interface ITokenBuilderService { 8 | 9 | String build(TokenClaims tokenClaims, SecretKey key); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/cleanup/ITokenCleanupService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.cleanup; 2 | 3 | public interface ITokenCleanupService { 4 | 5 | void cleanupAllTokens(); 6 | 7 | void cleanupExpiredTokens(); 8 | 9 | void cleanupRevokedTokens(); 10 | 11 | void cleanupInactiveTokens(); 12 | 13 | void cleanupBlacklistedTokens(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/key/IJwtKeyService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.key; 2 | 3 | import javax.crypto.SecretKey; 4 | 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public interface IJwtKeyService { 8 | 9 | @NotNull SecretKey generateKey(); 10 | 11 | boolean isValidKey(byte @NotNull [] key); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/lifecycle/ITokenLifecycleService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.lifecycle; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.TokenStateEnum; 4 | 5 | public interface ITokenLifecycleService { 6 | 7 | void initiateToken(String token, String username); 8 | 9 | void activateToken(String token); 10 | 11 | void refreshToken(String oldToken, String newToken); 12 | 13 | void expireToken(String token); 14 | 15 | void revokeToken(String token); 16 | 17 | TokenStateEnum getTokenState(String token); 18 | 19 | void handleExpiredToken(String token); 20 | 21 | void markTokenAsExpired(String token, String reason); 22 | 23 | void handleTokenAccess(String token, String operation); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/ratelimit/ITokenRateLimitService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.ratelimit; 2 | 3 | public interface ITokenRateLimitService { 4 | 5 | void checkRateLimit(String key); 6 | 7 | void recordAttempt(String key); 8 | 9 | void clearAttempts(String key); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/repository/ITokenRepositoryService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.repository; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.JwtTokenEntity; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | public interface ITokenRepositoryService { 9 | 10 | Optional findByToken(String token); 11 | 12 | JwtTokenEntity findTokenOrThrow(String token); 13 | 14 | void updateToken(JwtTokenEntity tokenEntity); 15 | 16 | List findAllByUsername(String username); 17 | 18 | JwtTokenEntity save(JwtTokenEntity tokenEntity); 19 | 20 | void deleteByToken(String token); 21 | 22 | Optional findJwtTokenEntityByUserEntityUsername(String username); 23 | } -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/state/ITokenStateService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.state; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.enums.TokenStateEnum; 4 | 5 | public interface ITokenStateService { 6 | 7 | void updateTokenState(String token, TokenStateEnum state, String reason); 8 | 9 | void updateTokenAccess(String token, String operation); 10 | 11 | void revokeToken(String token, String reason); 12 | 13 | TokenStateEnum getTokenState(String token); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/validation/ITokenValidatorService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.validation; 2 | 3 | public interface ITokenValidatorService { 4 | 5 | void validate(String token); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/validation/impl/TokenExpirationValidatorImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 4 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.ITokenValidatorService; 5 | import io.jsonwebtoken.Claims; 6 | import io.jsonwebtoken.ExpiredJwtException; 7 | import io.jsonwebtoken.JwtParser; 8 | import lombok.RequiredArgsConstructor; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.Date; 13 | 14 | @Slf4j 15 | @Component 16 | @RequiredArgsConstructor 17 | public class TokenExpirationValidatorImpl implements ITokenValidatorService { 18 | 19 | private final ExceptionShortComponent exceptionShortComponent; 20 | 21 | private final JwtParser jwtParser; 22 | 23 | @Override 24 | public void validate(String token) { 25 | try { 26 | Claims claims = jwtParser.parseSignedClaims(token).getPayload(); 27 | if (claims.getExpiration().before(new Date())) { 28 | throw exceptionShortComponent.tokenExpiredException("auth.token.expired"); 29 | } 30 | } catch (ExpiredJwtException e) { 31 | log.error("Token has expired: {}", e.getMessage()); 32 | throw exceptionShortComponent.tokenExpiredException("auth.token.expired"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/validation/impl/TokenFormatValidatorServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 4 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.ITokenValidatorService; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.util.StringUtils; 9 | 10 | @Slf4j 11 | @Component 12 | @RequiredArgsConstructor 13 | public class TokenFormatValidatorServiceImpl implements ITokenValidatorService { 14 | 15 | private static final int EXPECTED_PARTS = 3; 16 | 17 | private final ExceptionShortComponent exceptionShortComponent; 18 | 19 | @Override 20 | public void validate(String token) { 21 | if (!StringUtils.hasText(token)) { 22 | throw exceptionShortComponent.tokenInvalidException("auth.token.empty"); 23 | } 24 | 25 | String[] parts = token.split("\\."); 26 | if (parts.length != EXPECTED_PARTS) { 27 | throw exceptionShortComponent.jwtTokenInvalidFormatException("auth.token.invalid.format"); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/validation/impl/TokenSignatureValidatorImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 4 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.ITokenValidatorService; 5 | import io.jsonwebtoken.JwtParser; 6 | import io.jsonwebtoken.security.SignatureException; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Slf4j 12 | @Component 13 | @RequiredArgsConstructor 14 | public class TokenSignatureValidatorImpl implements ITokenValidatorService { 15 | 16 | private final ExceptionShortComponent exceptionShortComponent; 17 | 18 | private final JwtParser jwtParser; 19 | 20 | @Override 21 | public void validate(String token) { 22 | try { 23 | this.jwtParser.parseSignedClaims(token); 24 | } catch (SignatureException e) { 25 | log.error("Invalid JWT signature: {}", e.getMessage()); 26 | throw exceptionShortComponent.jwtTokenSignatureException("auth.token.signature.invalid"); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/token/validation/impl/TokenValidationChainImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.service.security.token.validation.ITokenValidatorService; 4 | import jakarta.annotation.PostConstruct; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Component 12 | @RequiredArgsConstructor 13 | public class TokenValidationChainImpl { 14 | 15 | private final TokenFormatValidatorServiceImpl tokenFormatValidator; 16 | 17 | private final TokenSignatureValidatorImpl tokenSignatureValidator; 18 | 19 | private final TokenExpirationValidatorImpl tokenExpirationValidator; 20 | 21 | private final TokenClaimsValidatorImpl tokenClaimsValidator; 22 | 23 | private final TokenHeaderValidatorImpl tokenHeaderValidator; 24 | 25 | private List validators; 26 | 27 | @PostConstruct 28 | public void initializeValidators() { 29 | this.validators = new ArrayList<>(); 30 | this.validators.add(this.tokenHeaderValidator); // Add header validation first 31 | this.validators.add(this.tokenFormatValidator); // Then format 32 | this.validators.add(this.tokenSignatureValidator); // Then signature 33 | this.validators.add(this.tokenExpirationValidator); // Then expiration 34 | this.validators.add(this.tokenClaimsValidator); // Finally, claims 35 | } 36 | 37 | public void validateToken(String token) { 38 | this.validators.forEach(validator -> validator.validate(token)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/security/user/IUserSecurityService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.security.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.security.UserSecurityDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 5 | 6 | import org.springframework.security.core.userdetails.UserDetailsService; 7 | 8 | public interface IUserSecurityService extends UserDetailsService { 9 | 10 | UserSecurityDTO findByUsername(String username); 11 | 12 | UserEntity findUserEntityByUsername(String username); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/IUserService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserProfileDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 5 | 6 | public interface IUserService { 7 | 8 | UserEntity getUserEntityById(int id); 9 | 10 | UserProfileDTO getUserProfile(int id); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/developer/IDeveloperService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.developer; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.developer.DeveloperDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.developer.DeveloperDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.developer.CreateDeveloperVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.developer.DeveloperFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.developer.UpdateDeveloperVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface IDeveloperService { 12 | 13 | DeveloperDTO createDeveloper(CreateDeveloperVO createDeveloperVO); 14 | 15 | DeveloperDTO updateDeveloper(UpdateDeveloperVO updateDeveloperVO); 16 | 17 | DeveloperDTO getDeveloperById(Integer id); 18 | 19 | DeveloperDetailDTO getDeveloperDetailById(Integer id); 20 | 21 | UserEntity getDeveloperEntityById(Integer id); 22 | 23 | Page searchDevelopers(DeveloperFilterVO filterVO); 24 | 25 | DeveloperDTO changeDeveloperStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteDeveloper(Integer id); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/editor/IEditorService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.editor; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.editor.EditorDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.editor.EditorDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.editor.CreateEditorVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.editor.EditorFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.editor.UpdateEditorVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface IEditorService { 12 | 13 | EditorDTO createEditor(CreateEditorVO createEditorVO); 14 | 15 | EditorDTO updateEditor(UpdateEditorVO updateEditorVO); 16 | 17 | EditorDTO getEditorById(Integer id); 18 | 19 | EditorDetailDTO getEditorDetailById(Integer id); 20 | 21 | UserEntity getEditorEntityById(Integer id); 22 | 23 | Page searchEditors(EditorFilterVO filterVO); 24 | 25 | EditorDTO changeEditorStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteEditor(Integer id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/guest/IGuestService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.guest; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.guest.GuestDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.guest.GuestDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.guest.CreateGuestVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.guest.UpdateGuestVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.guest.GuestFilterVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface IGuestService { 12 | 13 | GuestDTO createGuest(CreateGuestVO createGuestVO); 14 | 15 | GuestDTO updateGuest(UpdateGuestVO updateGuestVO); 16 | 17 | GuestDTO getGuestById(Integer id); 18 | 19 | GuestDetailDTO getGuestDetailById(Integer id); 20 | 21 | UserEntity getGuestEntityById(Integer id); 22 | 23 | Page searchGuests(GuestFilterVO filterVO); 24 | 25 | GuestDTO changeGuestStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteGuest(Integer id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.impl; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.UserProfileDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.exceptions.util.ExceptionShortComponent; 5 | import com.spacecodee.springbootsecurityopentemplate.mappers.user.IUserMapper; 6 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 7 | import com.spacecodee.springbootsecurityopentemplate.persistence.repository.user.IUserRepository; 8 | import com.spacecodee.springbootsecurityopentemplate.service.user.IUserService; 9 | import lombok.RequiredArgsConstructor; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | 13 | @Slf4j 14 | @Service 15 | @RequiredArgsConstructor 16 | public class UserServiceImpl implements IUserService { 17 | 18 | private final IUserRepository userRepository; 19 | private final IUserMapper userMapper; 20 | private final ExceptionShortComponent exceptionShortComponent; 21 | 22 | @Override 23 | public UserEntity getUserEntityById(int id) { 24 | return this.userRepository.findById(id) 25 | .orElseThrow( 26 | () -> this.exceptionShortComponent.objectNotFoundException("user.not.found", String.valueOf(id))); 27 | } 28 | 29 | @Override 30 | public UserProfileDTO getUserProfile(int id) { 31 | UserEntity userEntity = this.getUserEntityById(id); 32 | return this.userMapper.toProfileDTO(userEntity); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/manager/IManagerService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.manager; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.manager.ManagerDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.manager.ManagerDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.manager.CreateManagerVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.manager.ManagerFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.manager.UpdateManagerVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface IManagerService { 12 | 13 | ManagerDTO createManager(CreateManagerVO createManagerVO); 14 | 15 | ManagerDTO updateManager(UpdateManagerVO updateManagerVO); 16 | 17 | ManagerDTO getManagerById(Integer id); 18 | 19 | ManagerDetailDTO getManagerDetailById(Integer id); 20 | 21 | UserEntity getManagerEntityById(Integer id); 22 | 23 | Page searchManagers(ManagerFilterVO filterVO); 24 | 25 | ManagerDTO changeManagerStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteManager(Integer id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/system/admin/ISystemAdminService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.system.admin; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.system.admin.SystemAdminDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.system.admin.SystemAdminDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.system.admin.CreateSystemAdminVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.system.admin.SystemAdminFilterVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.system.admin.UpdateSystemAdminVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface ISystemAdminService { 12 | 13 | SystemAdminDTO createSystemAdmin(CreateSystemAdminVO createSystemAdminVO); 14 | 15 | SystemAdminDTO updateSystemAdmin(UpdateSystemAdminVO updateSystemAdminVO); 16 | 17 | SystemAdminDTO getSystemAdminById(Integer id); 18 | 19 | SystemAdminDetailDTO getSystemAdminDetailById(Integer id); 20 | 21 | UserEntity getSystemAdminEntityById(Integer id); 22 | 23 | Page searchSystemAdmins(SystemAdminFilterVO filterVO); 24 | 25 | SystemAdminDTO changeSystemAdminStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteSystemAdmin(Integer id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/service/user/viewer/IViewerService.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.service.user.viewer; 2 | 3 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.viewer.ViewerDTO; 4 | import com.spacecodee.springbootsecurityopentemplate.data.dto.user.viewer.ViewerDetailDTO; 5 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.viewer.CreateViewerVO; 6 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.viewer.UpdateViewerVO; 7 | import com.spacecodee.springbootsecurityopentemplate.data.vo.user.viewer.ViewerFilterVO; 8 | import com.spacecodee.springbootsecurityopentemplate.persistence.entity.UserEntity; 9 | import org.springframework.data.domain.Page; 10 | 11 | public interface IViewerService { 12 | 13 | ViewerDTO createViewer(CreateViewerVO createViewerVO); 14 | 15 | ViewerDTO updateViewer(UpdateViewerVO updateViewerVO); 16 | 17 | ViewerDTO getViewerById(Integer id); 18 | 19 | ViewerDetailDTO getViewerDetailById(Integer id); 20 | 21 | UserEntity getViewerEntityById(Integer id); 22 | 23 | Page searchViewers(ViewerFilterVO filterVO); 24 | 25 | ViewerDTO changeViewerStatus(Integer id, Boolean status); 26 | 27 | boolean existsByUsername(String username); 28 | 29 | boolean existsByEmail(String email); 30 | 31 | void deleteViewer(Integer id); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/spacecodee/springbootsecurityopentemplate/utils/LocaleUtils.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate.utils; 2 | 3 | import org.springframework.context.i18n.LocaleContextHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class LocaleUtils { 8 | 9 | public String getCurrentLocale() { 10 | return LocaleContextHolder.getLocale().getLanguage(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/api/api-doc.properties: -------------------------------------------------------------------------------- 1 | message.login=Login -------------------------------------------------------------------------------- /src/main/resources/application-local.properties.example: -------------------------------------------------------------------------------- 1 | # Database configuration for PostgreSQL using docker in a devcontainer 2 | spring.datasource.url=jdbc:postgresql://postgres_db:5432/${POSTGRES_DB} 3 | spring.datasource.username=${POSTGRES_USER} 4 | spring.datasource.password=${POSTGRES_PASSWORD} 5 | security.jwt.expiration-in-minutes=30 6 | security.jwt.max-refresh-count=5 7 | security.token.rate-limit.max-attempts=5 8 | security.token.rate-limit.window-minutes=2 9 | security.cache.max-size=1000 10 | security.cache.expire-after-minutes=30 11 | security.cache.refresh-rate-minutes=60 12 | security.cache.rate-limit-duration-minutes=10 13 | # Security Jwt 14 | Use the next web page to generate a secret key: https://www.base64encode.org/ 15 | security.jwt.secret-key=Yoursupersecretkey 16 | security.cors.allowed-origins=x.space,y.com,z.com 17 | security.cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS,PATCH 18 | security.cors.allowed-headers=Authorization,Content-Type,Accept-Language 19 | # Rate Limit Configuration 20 | security.rate-limit.max-attempts=5 21 | security.rate-limit.duration-minutes=10 22 | # Roles 23 | role.default.admin=SYSTEM_ADMIN 24 | role.default.developer=DEVELOPER 25 | role.default.manager=MANAGER 26 | role.default.editor=EDITOR 27 | role.default.viewer=VIEWER 28 | role.default.guest=GUEST 29 | # Token Cleanup Configuration 30 | security.token.cleanup.expired.cron=0 0 */1 * * * 31 | security.token.cleanup.revoked.cron=0 30 */2 * * * 32 | security.token.cleanup.inactive.cron=0 0 0 * * * 33 | security.token.cleanup.blacklisted.cron=0 15 */3 * * * -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/test/java/com/spacecodee/springbootsecurityopentemplate/SpringbootSecurityOpenTemplateApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.spacecodee.springbootsecurityopentemplate; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringbootSecurityOpenTemplateApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | --------------------------------------------------------------------------------