Skip to content

Commit

Permalink
Merge pull request #107 from anishmu20/feature/api-validation
Browse files Browse the repository at this point in the history
Feature/api validation
  • Loading branch information
Guhapriya01 authored Nov 9, 2024
2 parents fa6ce6c + 1782903 commit 70142f9
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 8 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.3.4</version>
</dependency>

</dependencies>

<build>
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/libraryman_api/book/BookController.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.libraryman_api.book;

import com.libraryman_api.exception.ResourceNotFoundException;

import jakarta.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -75,7 +75,7 @@ public ResponseEntity<BookDto> getBookById(@PathVariable int id) {
*/
@PostMapping
@PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')")
public BookDto addBook(@RequestBody BookDto bookDto) {
public BookDto addBook(@Valid @RequestBody BookDto bookDto) {
return bookService.addBook(bookDto);
}

Expand All @@ -88,7 +88,7 @@ public BookDto addBook(@RequestBody BookDto bookDto) {
*/
@PutMapping("/{id}")
@PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')")
public BookDto updateBook(@PathVariable int id, @RequestBody BookDto bookDtoDetails) {
public BookDto updateBook(@PathVariable int id, @Valid @RequestBody BookDto bookDtoDetails) {
return bookService.updateBook(id, bookDtoDetails);
}

Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/libraryman_api/book/BookDto.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
package com.libraryman_api.book;

import jakarta.validation.constraints.*;

public class BookDto {


private int bookId;
@NotBlank(message = "Title is required ")
@Size(min = 1,max = 255,message = "Title must be between 1 and 255 characters")
private String title;

@NotBlank(message = "Author is required")
@Size(min = 1, max = 100, message = "Author name must be between 1 and 100 characters")
private String author;

@NotBlank(message = "isbn is required")
@Pattern(regexp = "^(978|979)-\\d{10}$", message = "Invalid ISBN format. Format must be '978-XXXXXXXXXX' or '979-XXXXXXXXXX'")
private String isbn;

@NotBlank(message = "Publisher is required")
@Size(min = 1, max = 100, message = "Publisher name must be between 1 and 100 characters")
private String publisher;

@Min(value = 1500, message = "Published year must be at least 1500")
@Max(value = 2100, message = "Published year cannot be more than 2100")
private int publishedYear;

@NotBlank(message = "Genre is required")
@Size(min = 1, max = 50, message = "Genre must be between 1 and 50 characters")
private String genre;

@Min(value = 0, message = "Copies available cannot be negative")
private int copiesAvailable;

public BookDto(int bookId, String title, String author, String isbn, String publisher, int publishedYear, String genre, int copiesAvailable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.libraryman_api.borrowing;

import com.libraryman_api.exception.ResourceNotFoundException;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -66,7 +67,7 @@ public Page<BorrowingsDto> getAllBorrowings(@PageableDefault(page = 0, size = 5,
*/
@PostMapping
@PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN') or (hasRole('USER') and #borrowingsDto.member.memberId == authentication.principal.memberId)")
public BorrowingsDto borrowBook(@RequestBody BorrowingsDto borrowingsDto) {
public BorrowingsDto borrowBook(@Valid @RequestBody BorrowingsDto borrowingsDto) {
return borrowingService.borrowBook(borrowingsDto);
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/libraryman_api/borrowing/BorrowingsDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
import com.libraryman_api.book.BookDto;
import com.libraryman_api.fine.Fines;
import com.libraryman_api.member.dto.MembersDto;
import jakarta.validation.constraints.NotNull;

import java.util.Date;

public class BorrowingsDto {

private int borrowingId;
@NotNull(message = "Book is required")
private BookDto book;
private Fines fine;
@NotNull(message = "Member is required")
private MembersDto member;

private Date borrowDate;
private Date dueDate;
private Date returnDate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;

import java.util.Date;
import java.util.*;

/**
* Global exception handler for the LibraryMan API. This class provides
Expand Down Expand Up @@ -69,4 +73,18 @@ public ResponseEntity<?> invalidPasswordException(InvalidPasswordException ex, W
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String,Object>> MethodArgumentNotValidException(MethodArgumentNotValidException ex){
List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
HashMap<String,Object> map = new HashMap<>();
allErrors.forEach(objectError -> {
String message=objectError.getDefaultMessage();
String field=((FieldError) objectError).getField();
map.put(field,message);
});

return new ResponseEntity<>(map,HttpStatus.BAD_REQUEST);
}

}
5 changes: 3 additions & 2 deletions src/main/java/com/libraryman_api/member/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.libraryman_api.member.dto.MembersDto;
import com.libraryman_api.member.dto.UpdateMembersDto;
import com.libraryman_api.member.dto.UpdatePasswordDto;
import jakarta.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -86,7 +87,7 @@ public ResponseEntity<MembersDto> getMemberById(@PathVariable int id) {
*/
@PutMapping("/{id}")
@PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN') or (hasRole('USER') and #id == authentication.principal.memberId)")
public MembersDto updateMember(@PathVariable int id, @RequestBody UpdateMembersDto membersDtoDetails) {
public MembersDto updateMember(@PathVariable int id,@Valid @RequestBody UpdateMembersDto membersDtoDetails) {
return memberService.updateMember(id, membersDtoDetails);
}

Expand All @@ -113,7 +114,7 @@ public void deleteMember(@PathVariable int id) {
@PutMapping("/{id}/password")
@PreAuthorize("#id == authentication.principal.memberId")
public ResponseEntity<?> updatePassword(@PathVariable int id,
@RequestBody UpdatePasswordDto updatePasswordDto) {
@Valid @RequestBody UpdatePasswordDto updatePasswordDto) {
memberService.updatePassword(id, updatePasswordDto);
return ResponseEntity.ok("Password updated successfully.");
}
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/libraryman_api/member/dto/MembersDto.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
package com.libraryman_api.member.dto;

import com.libraryman_api.member.Role;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

import java.util.Date;

public class MembersDto {

private int memberId;
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
private String name;
@NotBlank(message = "Username is required")
@Size(min = 4, max = 50, message = "Username must be between 4 and 50 characters")
private String username;

@Pattern(regexp = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$", message = "Please enter a valid email address (e.g., [email protected])")
@NotBlank(message = "Email field cannot be empty. Please provide a valid email address.")
private String email;

@NotBlank(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters long")
@Pattern(regexp = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[@#$%^&+=]).*$",
message = "Password must contain at least one letter, one number, and one special character")
private String password;


private Role role;

private Date membershipDate;

public MembersDto(int memberId, String name, String username, String email, String password, Role role, Date membershipDate) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package com.libraryman_api.member.dto;

public class UpdateMembersDto {
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

public class UpdateMembersDto {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be between 2 and 100 characters")
private String name;
@NotBlank(message = "Username is required")
@Size(min = 4, max = 50, message = "Username must be between 4 and 50 characters")
private String username;
@Pattern(regexp = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$", message = "Please enter a valid email address (e.g., [email protected])")
@NotBlank(message = "Email field cannot be empty. Please provide a valid email address.")
private String email;

public UpdateMembersDto(String name, String username, String email) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.libraryman_api.member.dto;

public class UpdatePasswordDto {
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

public class UpdatePasswordDto {
private String currentPassword;

@NotBlank(message = "New Password is required")
@Size(min = 8, message = "Password must be at least 8 characters long")
@Pattern(regexp = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[@#$%^&+=]).*$",
message = "Password must contain at least one letter, one number, and one special character")
private String newPassword;

public UpdatePasswordDto(String currentPassword, String newPassword) {
Expand Down

0 comments on commit 70142f9

Please sign in to comment.