From f50f05b57e1dfdeb5bda3b8850fed3ab09074e85 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:44:03 +0200 Subject: [PATCH 1/9] fix: Separate error response --- .../exceptions/UnauthorizedException.java | 4 ++-- .../springrestframework/web/responses/ErrorResponse.java | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/github/nikanique/springrestframework/exceptions/UnauthorizedException.java b/src/main/java/io/github/nikanique/springrestframework/exceptions/UnauthorizedException.java index dab33ac..8f9a060 100644 --- a/src/main/java/io/github/nikanique/springrestframework/exceptions/UnauthorizedException.java +++ b/src/main/java/io/github/nikanique/springrestframework/exceptions/UnauthorizedException.java @@ -3,8 +3,8 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; -@ResponseStatus(HttpStatus.UNAUTHORIZED) -public class UnauthorizedException extends RuntimeException { +@ResponseStatus(HttpStatus.FORBIDDEN) +public class UnauthorizedException extends BaseException { public UnauthorizedException(String message) { super(message); diff --git a/src/main/java/io/github/nikanique/springrestframework/web/responses/ErrorResponse.java b/src/main/java/io/github/nikanique/springrestframework/web/responses/ErrorResponse.java index 1402b66..ac3d321 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/responses/ErrorResponse.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/responses/ErrorResponse.java @@ -1,15 +1,10 @@ package io.github.nikanique.springrestframework.web.responses; -import lombok.AllArgsConstructor; import lombok.Data; -import java.util.Map; - @Data -@AllArgsConstructor public class ErrorResponse { private String message; - private Map fields; public ErrorResponse(String message) { this.message = message; From 2cf3fad6eebfcb37dcd5d15d58b01e02ccf23924 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:44:29 +0200 Subject: [PATCH 2/9] fix: Handle UnauthorizedException --- .../advices/GlobalExceptionHandler.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/nikanique/springrestframework/advices/GlobalExceptionHandler.java b/src/main/java/io/github/nikanique/springrestframework/advices/GlobalExceptionHandler.java index d536a12..af45ac1 100644 --- a/src/main/java/io/github/nikanique/springrestframework/advices/GlobalExceptionHandler.java +++ b/src/main/java/io/github/nikanique/springrestframework/advices/GlobalExceptionHandler.java @@ -3,8 +3,10 @@ import io.github.nikanique.springrestframework.exceptions.BadRequestException; import io.github.nikanique.springrestframework.exceptions.BaseException; +import io.github.nikanique.springrestframework.exceptions.UnauthorizedException; import io.github.nikanique.springrestframework.exceptions.ValidationException; import io.github.nikanique.springrestframework.web.responses.ErrorResponse; +import io.github.nikanique.springrestframework.web.responses.ValidationErrorResponse; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; @@ -15,10 +17,15 @@ public class GlobalExceptionHandler { @ExceptionHandler({ValidationException.class, BadRequestException.class}) public ResponseEntity handleValidationException(BaseException ex) { - ErrorResponse errorResponse = new ErrorResponse(ex.getMessage(), ex.getErrors()); - return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST); + ValidationErrorResponse validationErrorResponse = new ValidationErrorResponse(ex.getMessage(), ex.getErrors()); + return new ResponseEntity<>(validationErrorResponse, HttpStatus.BAD_REQUEST); } + @ExceptionHandler({UnauthorizedException.class}) + public ResponseEntity handleUnauthorizedException(BaseException ex) { + ErrorResponse errorResponse = new ErrorResponse(ex.getMessage()); + return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN); + } } From 1209b3ae204a384a369b3055d4d5910b6fb70d58 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:45:47 +0200 Subject: [PATCH 3/9] fix: change the ValidationErrorResponse inheritance --- .../web/responses/ValidationErrorResponse.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/io/github/nikanique/springrestframework/web/responses/ValidationErrorResponse.java diff --git a/src/main/java/io/github/nikanique/springrestframework/web/responses/ValidationErrorResponse.java b/src/main/java/io/github/nikanique/springrestframework/web/responses/ValidationErrorResponse.java new file mode 100644 index 0000000..428c64d --- /dev/null +++ b/src/main/java/io/github/nikanique/springrestframework/web/responses/ValidationErrorResponse.java @@ -0,0 +1,15 @@ +package io.github.nikanique.springrestframework.web.responses; + +import lombok.Data; + +import java.util.Map; + +@Data +public class ValidationErrorResponse extends ErrorResponse { + private Map fields; + + public ValidationErrorResponse(String message, Map fields) { + super(message); + this.fields = fields; + } +} \ No newline at end of file From 02ca76732d57ba0c6f1af86ff8bf4d0121f522cd Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:49:02 +0200 Subject: [PATCH 4/9] feat: Add support for Spring security Authorities and Roles --- pom.xml | 7 +++- .../controllers/BaseGenericController.java | 38 +++++++++++++++++++ .../controllers/GenericCommandController.java | 8 +++- .../controllers/GenericCreateController.java | 1 + .../controllers/GenericDeleteController.java | 10 +++++ .../controllers/GenericListController.java | 2 +- .../controllers/GenericQueryController.java | 4 +- .../GenericRetrieveController.java | 4 +- .../controllers/GenericUpdateController.java | 5 ++- 9 files changed, 69 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 5e372cd..e258b91 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ io.github.nikanique spring-rest-framework - 1.0.2 + 2.0.0 jar spring-rest-framework @@ -72,6 +72,11 @@ spring-boot-starter-web provided + + org.springframework.boot + spring-boot-starter-security + provided + net.bytebuddy byte-buddy diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/BaseGenericController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/BaseGenericController.java index a682234..c334319 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/BaseGenericController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/BaseGenericController.java @@ -1,6 +1,7 @@ package io.github.nikanique.springrestframework.web.controllers; +import io.github.nikanique.springrestframework.exceptions.UnauthorizedException; import io.github.nikanique.springrestframework.orm.SearchCriteria; import io.github.nikanique.springrestframework.serializer.Serializer; import io.swagger.v3.oas.models.Operation; @@ -11,10 +12,14 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.method.HandlerMethod; import java.lang.reflect.ParameterizedType; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * This is abstract controller. It is a base controller for all generic controllers. @@ -31,12 +36,16 @@ public abstract class BaseGenericController> endpointsRequiredAuthorities; @Autowired public BaseGenericController(@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") ModelRepository repository) { this.repository = repository; + this.endpointsRequiredAuthorities = new HashMap<>(); + this.configRequiredAuthorities(this.endpointsRequiredAuthorities); } + @Override @Autowired public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -78,4 +87,33 @@ public void setSerializer(Serializer serializer) { this.serializer = serializer; } + protected void configRequiredAuthorities(Map> authorities) { + authorities.put("GET", null); + authorities.put("POST", null); + authorities.put("PUT", null); + authorities.put("PATCH", null); + authorities.put("DELETE", null); + } + + protected List getRequiredAuthorities(String HttpMethod) { + return this.endpointsRequiredAuthorities.getOrDefault(HttpMethod, null); + } + + protected boolean hasAuthorities(List requiredAuthorities) { + if (requiredAuthorities == null) { + return true; + } + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return requiredAuthorities.stream().anyMatch(authority -> + authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(authority)) + ); + } + + protected void authorizeRequest(String HttpMethod) { + List requiredAuthorities = getRequiredAuthorities(HttpMethod); + if (!hasAuthorities(requiredAuthorities)) { + throw new UnauthorizedException("You do not have permission to perform this action."); + } + } } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCommandController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCommandController.java index 27f4d6c..e20ad7a 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCommandController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCommandController.java @@ -82,24 +82,28 @@ protected Filter configLookupFilter() { @PostMapping("/") public ResponseEntity post(HttpServletRequest request) throws IOException { + this.authorizeRequest("POST"); return this.create(this, request); } @PutMapping("/{lookup}") public ResponseEntity put(@PathVariable(name = "lookup") Object lookupValue, HttpServletRequest request) throws Throwable { + this.authorizeRequest("PUT"); return this.update(this, lookupValue, request); } @PatchMapping("/{lookup}") - public ResponseEntity partialUpdate(@PathVariable(name = "lookup") Object lookupValue, HttpServletRequest request) throws Throwable { + public ResponseEntity patch(@PathVariable(name = "lookup") Object lookupValue, HttpServletRequest request) throws Throwable { + this.authorizeRequest("PATCH"); return this.partialUpdate(this, lookupValue, request); } @DeleteMapping("/{lookup}") public ResponseEntity delete(HttpServletRequest request, @PathVariable(name = "lookup") Object lookupValue) { - return deleteObject(this, request, lookupValue); + this.authorizeRequest("DELETE"); + return this.deleteObject(this, lookupValue, request); } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCreateController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCreateController.java index 6b63c36..c30503b 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCreateController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericCreateController.java @@ -74,6 +74,7 @@ public Class getCreateResponseBodyDTO() { @PostMapping("/") public ResponseEntity post(HttpServletRequest request) throws IOException { + this.authorizeRequest("POST"); return this.create(this, request); } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericDeleteController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericDeleteController.java index ddf6115..4afebba 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericDeleteController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericDeleteController.java @@ -7,9 +7,13 @@ import io.github.nikanique.springrestframework.services.QueryService; import io.swagger.v3.oas.models.Operation; import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; import lombok.Getter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.method.HandlerMethod; /** @@ -64,6 +68,12 @@ protected Filter configLookupFilter() { return new Filter("id", FilterOperation.EQUAL, FieldType.INTEGER); } + @DeleteMapping("/{lookup}") + public ResponseEntity delete(HttpServletRequest request, @PathVariable(name = "lookup") Object lookupValue) { + this.authorizeRequest("DELETE"); + return deleteObject(this, lookupValue, request); + } + public void customizeOperationForController(Operation operation, HandlerMethod handlerMethod) { if (handlerMethod.getMethod().getName().equals("delete")) { generateDeleteSchema(operation, getLookupFilter()); diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericListController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericListController.java index b73ffd8..04785ba 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericListController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericListController.java @@ -100,7 +100,7 @@ public ResponseEntity> get( @RequestParam(defaultValue = "10") int size, @RequestParam(defaultValue = "") String sortBy, @RequestParam(defaultValue = "ASC") Sort.Direction direction) throws Throwable { - + this.authorizeRequest("GET"); return this.list(this, request, page, size, sortBy, direction); } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericQueryController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericQueryController.java index 027e5bb..e050ff5 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericQueryController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericQueryController.java @@ -120,7 +120,7 @@ public ResponseEntity> get( @RequestParam(defaultValue = "10") int size, @RequestParam(defaultValue = "") String sortBy, @RequestParam(defaultValue = "ASC") Sort.Direction direction) throws Throwable { - + this.authorizeRequest("GET"); return this.list(this, request, page, size, sortBy, direction); } @@ -128,7 +128,7 @@ public ResponseEntity> get( public ResponseEntity getByLookupValue( HttpServletRequest request, @PathVariable(name = "lookup") Object lookupValue) throws Throwable { - + this.authorizeRequest("GET"); return this.retrieve(this, request, lookupValue); } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericRetrieveController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericRetrieveController.java index d327c12..bf26b8d 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericRetrieveController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericRetrieveController.java @@ -75,7 +75,7 @@ protected String getQueryMethodName() { private void postConstruct() { this.queryService = QueryService.getInstance(this.getModel(), this.repository, this.context); } - + protected Class getRetrieveResponseDTO() { return getDTO(); @@ -93,7 +93,7 @@ protected Filter configLookupFilter() { public ResponseEntity getByLookupValue( HttpServletRequest request, @PathVariable(name = "lookup") Object lookupValue) throws Throwable { - + this.authorizeRequest("GET"); return this.retrieve(this, request, lookupValue); } diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericUpdateController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericUpdateController.java index 8c95c79..2bf488b 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericUpdateController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/GenericUpdateController.java @@ -99,13 +99,14 @@ protected Filter configLookupFilter() { @PutMapping("/{lookup}") public ResponseEntity update(@PathVariable(name = "lookup") Object lookupValue, HttpServletRequest request) throws Throwable { - + this.authorizeRequest("PUT"); return this.update(this, lookupValue, request); } @PatchMapping("/{lookup}") public ResponseEntity patch(@PathVariable(name = "lookup") Object lookupValue, HttpServletRequest request) throws Throwable { - return partialUpdate(this, lookupValue, request); + this.authorizeRequest("PATCH"); + return this.partialUpdate(this, lookupValue, request); } From c2bd6a1ed8e4ecddf92b535106d960b016004102 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:49:37 +0200 Subject: [PATCH 5/9] fix: Add message to list response --- .../springrestframework/web/controllers/ListController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/ListController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/ListController.java index 48c9208..10b6813 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/ListController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/ListController.java @@ -61,7 +61,7 @@ default ResponseEntity list(BaseGenericController controller, HttpServletRequest Page entityPage = getQueryService().getPagedlist(searchCriteriaList, page, size, direction, sortColumn, getQueryMethod()); List dtoList = entityPage.map(entity -> controller.getSerializer().serialize(entity, getListSerializerConfig())).getContent(); - PagedResponse response = new PagedResponse<>(dtoList, entityPage.getTotalElements()); + PagedResponse response = new PagedResponse<>(dtoList, entityPage.getTotalElements(), "OK"); return ResponseEntity.ok(response); } From ace61b08708c2175c72478a56999d8069f59c934 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:50:08 +0200 Subject: [PATCH 6/9] fix: raise exception om validation error --- .../springrestframework/web/controllers/CreateController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/CreateController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/CreateController.java index 5c75671..d3a01c3 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/CreateController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/CreateController.java @@ -41,7 +41,7 @@ default SerializerConfig configCreateSerializerFields() { default ResponseEntity create(BaseGenericController controller, HttpServletRequest request) throws IOException { String requestBody = this.getRequestBody(request); - Object dto = controller.getSerializer().deserialize(requestBody, getCreateRequestBodyDTO()); + Object dto = controller.getSerializer().deserialize(requestBody, getCreateRequestBodyDTO(), true); Model entity = this.getEntityHelper().fromDto(dto, this.getCreateRequestBodyDTO()); entity = getCommandService().create(entity); return ResponseEntity.status(HttpStatus.CREATED).body( From e3109fc66f3f64dd214967dfe07e5916e79ec1c5 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Tue, 24 Dec 2024 22:50:41 +0200 Subject: [PATCH 7/9] refactor: change arguments order --- .../springrestframework/web/controllers/DeleteController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/github/nikanique/springrestframework/web/controllers/DeleteController.java b/src/main/java/io/github/nikanique/springrestframework/web/controllers/DeleteController.java index da5edca..ae0670d 100644 --- a/src/main/java/io/github/nikanique/springrestframework/web/controllers/DeleteController.java +++ b/src/main/java/io/github/nikanique/springrestframework/web/controllers/DeleteController.java @@ -26,7 +26,7 @@ public interface DeleteController { Filter getLookupFilter(); - default ResponseEntity deleteObject(BaseGenericController controller, HttpServletRequest request, Object lookupValue) { + default ResponseEntity deleteObject(BaseGenericController controller, Object lookupValue, HttpServletRequest request) { List searchCriteriaList = SearchCriteria.fromValue(lookupValue, this.getLookupFilter()); searchCriteriaList = controller.filterByRequest(request, searchCriteriaList); From a5e39ef96c40939419903c77b3d431a6f385f91b Mon Sep 17 00:00:00 2001 From: birddevelper Date: Wed, 25 Dec 2024 21:52:42 +0200 Subject: [PATCH 8/9] fix: disable security by default --- .../configs/security/SecurityConfig.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/io/github/nikanique/springrestframework/configs/security/SecurityConfig.java diff --git a/src/main/java/io/github/nikanique/springrestframework/configs/security/SecurityConfig.java b/src/main/java/io/github/nikanique/springrestframework/configs/security/SecurityConfig.java new file mode 100644 index 0000000..c0b8e19 --- /dev/null +++ b/src/main/java/io/github/nikanique/springrestframework/configs/security/SecurityConfig.java @@ -0,0 +1,31 @@ +package io.github.nikanique.springrestframework.configs.security; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +@Order(Ordered.HIGHEST_PRECEDENCE) +class SpringRestFrameworkSecurityConfig { + + private static void disableAuthentication(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry authz) { + try { + authz.anyRequest().permitAll().and().csrf().disable(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Bean + public SecurityFilterChain SRFSecurityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(SpringRestFrameworkSecurityConfig::disableAuthentication); + return http.build(); + } +} \ No newline at end of file From 23a177ae1f6b25e477218b25e81faa5fbf1beff0 Mon Sep 17 00:00:00 2001 From: birddevelper Date: Wed, 25 Dec 2024 22:05:57 +0200 Subject: [PATCH 9/9] fix: upgrade the version --- README.md | 55 ++++++++++++++++++++++--------------------------------- pom.xml | 12 +++++------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index aaafe68..235bbe1 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,20 @@ framework. ## Features -- **Developer-Friendly**: Effortlessly generates web APIs while eliminating the need for - boilerplate code, simplifying the task of exposing standard endpoints (GET, POST, PUT, PATCH) for ORM entity. -- **Serialization**: The comprehensive and flexible serializer, integrated with Spring Data JPA, assists developers in - customizing the input and output in web APIs. -- **Filters**: Offers flexibility and powerful filtering in APIs to query data from database. +- **Developer-Friendly**: Simplifies API development by automatically generating web endpoints (GET, POST, PUT, PATCH) + for ORM entities, eliminating boilerplate code and streamlining common tasks. +- **Serialization**: Robust and flexible serializer, seamlessly integrated with Spring Data JPA, enabling + easy customization of API input and output formats. +- **Filtering**: Provides powerful and versatile filtering capabilities for querying data directly from the database. +- **Validation**: Ensures reliable endpoint validation with a wide range of rules and supports custom validation for + user input. +- **Security**: Built-in integration with Spring Security delivers secure access control, safeguarding APIs and + resources for authorized users. ## Requirements - Java 17+ - Spring Boot 3.0.0+ -- Spring Data JPA -- Spring Web MVC -- SpringDoc OpenAPI WebMVC UI 2.1.0+ ## Installation @@ -29,23 +30,11 @@ To install the Spring REST Framework, include the following dependencies in your ```xml - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-web - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.1.0 - + io.github.nikanique spring-rest-framework - 1.0.2 + 2.1.0 ``` @@ -64,7 +53,6 @@ To start using the library, follow these steps: For example, declare a Student model. ```java - import jakarta.persistence.Entity; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -73,20 +61,21 @@ To start using the library, follow these steps: @Entity @Data public class Student { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private String fullName; - private Integer age; - private String major; - - @ManyToOne(fetch = FetchType.EAGER) - @JoinColumn(name = "school_id") - private School school; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String fullName; + private Integer age; + private String major; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "school_id") + private School school; } ``` + Create Repository for you model. ```java import com.example.demo.model.Student; diff --git a/pom.xml b/pom.xml index e258b91..de5a5fa 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ io.github.nikanique spring-rest-framework - 2.0.0 + 2.1.0 jar spring-rest-framework @@ -43,13 +43,11 @@ org.springframework.boot spring-boot-starter - provided org.springdoc springdoc-openapi-starter-webmvc-ui 2.1.0 - provided org.springframework.boot @@ -59,23 +57,23 @@ org.springframework.boot spring-boot-starter-data-jpa - provided + 3.3.2 org.projectlombok lombok true - provided + 1.18.34 org.springframework.boot spring-boot-starter-web - provided + 3.3.2 org.springframework.boot spring-boot-starter-security - provided + 3.4.1 net.bytebuddy