diff --git a/pom.xml b/pom.xml index 80ba2de..59e0791 100644 --- a/pom.xml +++ b/pom.xml @@ -116,6 +116,11 @@ 3.3.4 + + org.springframework.boot + spring-boot-starter-actuator + + diff --git a/src/main/java/com/libraryman_api/book/BookController.java b/src/main/java/com/libraryman_api/book/BookController.java index a1d6545..803e0e9 100644 --- a/src/main/java/com/libraryman_api/book/BookController.java +++ b/src/main/java/com/libraryman_api/book/BookController.java @@ -19,7 +19,7 @@ * updating an existing book, and deleting a book. */ @RestController -@RequestMapping("/api/books") +@RequestMapping("/api") public class BookController { @Autowired @@ -34,7 +34,7 @@ public class BookController { * @return a {@link Page} of {@link BookDto} objects representing the books in the library. * The results are sorted by title by default and limited to 5 books per page. */ - @GetMapping + @GetMapping("/get-all-books") public Page getAllBooks(@PageableDefault(page = 0, size = 5, sort = "title") Pageable pageable, @RequestParam(required = false) String sortBy, @RequestParam(required = false) String sortDir) { @@ -59,7 +59,7 @@ public Page getAllBooks(@PageableDefault(page = 0, size = 5, sort = "ti * @return a {@link ResponseEntity} containing the {@link Book} object, if found. * @throws ResourceNotFoundException if the book with the specified ID is not found. */ - @GetMapping("/{id}") + @GetMapping("get-book-by-id/{id}") public ResponseEntity getBookById(@PathVariable int id) { return bookService.getBookById(id) .map(ResponseEntity::ok) @@ -72,7 +72,7 @@ public ResponseEntity getBookById(@PathVariable int id) { * @param bookDto the {@link Book} object representing the new book to add. * @return the added {@link Book} object. */ - @PostMapping + @PostMapping("/add-book") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public BookDto addBook(@Valid @RequestBody BookDto bookDto) { return bookService.addBook(bookDto); @@ -85,7 +85,7 @@ public BookDto addBook(@Valid @RequestBody BookDto bookDto) { * @param bookDtoDetails the {@link Book} object containing the updated book details. * @return the updated {@link Book} object. */ - @PutMapping("/{id}") + @PutMapping("update-book/{id}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public BookDto updateBook(@PathVariable int id, @Valid @RequestBody BookDto bookDtoDetails) { return bookService.updateBook(id, bookDtoDetails); @@ -96,7 +96,7 @@ public BookDto updateBook(@PathVariable int id, @Valid @RequestBody BookDto book * * @param id the ID of the book to delete. */ - @DeleteMapping("/{id}") + @DeleteMapping("delete-book/{id}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public void deleteBook(@PathVariable int id) { bookService.deleteBook(id); @@ -112,7 +112,7 @@ public void deleteBook(@PathVariable int id) { * @param pageable * @return */ - @GetMapping("/search") + @GetMapping("book/search") public ResponseEntity> searchBook(@RequestParam String keyword, @PageableDefault(page = 0, size = 5, sort = "title") Pageable pageable) { Page books = bookService.searchBook(keyword, pageable); if (!books.isEmpty()) diff --git a/src/main/java/com/libraryman_api/borrowing/BorrowingController.java b/src/main/java/com/libraryman_api/borrowing/BorrowingController.java index 5b11c55..e233cd5 100644 --- a/src/main/java/com/libraryman_api/borrowing/BorrowingController.java +++ b/src/main/java/com/libraryman_api/borrowing/BorrowingController.java @@ -16,7 +16,7 @@ * paying fines, and retrieving borrowing records. */ @RestController -@RequestMapping("/api/borrowings") +@RequestMapping("/api") public class BorrowingController { private final BorrowingService borrowingService; @@ -39,7 +39,7 @@ public BorrowingController(BorrowingService borrowingService) { * @return a {@link Page} of {@link Borrowings} representing all borrowings. * The results are sorted by borrow date by default and limited to 5 members per page. */ - @GetMapping + @GetMapping("/get-all-borrowings") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public Page getAllBorrowings(@PageableDefault(page = 0, size = 5, sort = "borrowDate") Pageable pageable, @RequestParam(required = false) String sortBy, @@ -65,7 +65,7 @@ public Page getAllBorrowings(@PageableDefault(page = 0, size = 5, * @param borrowingsDto the {@link Borrowings} object containing borrowing details. * @return the saved {@link Borrowings} object representing the borrowing record. */ - @PostMapping + @PostMapping("/borrow-book") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN') or (hasRole('USER') and #borrowingsDto.member.memberId == authentication.principal.memberId)") public BorrowingsDto borrowBook(@Valid @RequestBody BorrowingsDto borrowingsDto) { return borrowingService.borrowBook(borrowingsDto); @@ -76,7 +76,7 @@ public BorrowingsDto borrowBook(@Valid @RequestBody BorrowingsDto borrowingsDto) * * @param id the ID of the borrowing record to update. */ - @PutMapping("/{id}/return") + @PutMapping("/{id}/return-borrow-book") public BorrowingsDto returnBook(@PathVariable int id) { return borrowingService.returnBook(id); } @@ -87,7 +87,7 @@ public BorrowingsDto returnBook(@PathVariable int id) { * @param id the ID of the borrowing record for which the fine is being paid. * @return a message indicating the payment status. */ - @PutMapping("/{id}/pay") + @PutMapping("/borrowing/{id}/pay-fine") public String payFine(@PathVariable int id) { System.out.println("Pay Fine Id: " + id); return borrowingService.payFine(id); @@ -103,7 +103,7 @@ public String payFine(@PathVariable int id) { * @return a {@link Page} of {@link Borrowings} representing all borrowings for a specific member. * The results are sorted by borrow date by default and limited to 5 members per page. */ - @GetMapping("member/{memberId}") + @GetMapping("/get-all-borrowings-of-a-member/{memberId}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN') or (hasRole('USER') and #memberId == authentication.principal.memberId)") public Page getAllBorrowingsOfAMember(@PathVariable int memberId, @PageableDefault(page = 0, size = 5, sort = "borrowDate") Pageable pageable, @@ -131,7 +131,7 @@ public Page getAllBorrowingsOfAMember(@PathVariable int memberId, * @return the {@link Borrowings} object representing the borrowing record. * @throws ResourceNotFoundException if the borrowing record with the specified ID is not found. */ - @GetMapping("{borrowingId}") + @GetMapping("/get-borrowing-by-id/{borrowingId}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public BorrowingsDto getBorrowingById(@PathVariable int borrowingId) { return borrowingService.getBorrowingById(borrowingId) diff --git a/src/main/java/com/libraryman_api/fine/Fine.java b/src/main/java/com/libraryman_api/fine/Fine.java index a791286..6edce95 100644 --- a/src/main/java/com/libraryman_api/fine/Fine.java +++ b/src/main/java/com/libraryman_api/fine/Fine.java @@ -14,7 +14,7 @@ public class Fine { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fine_id_generator") @SequenceGenerator(name = "fine_id_generator", sequenceName = "fine_id_sequence", allocationSize = 1) - @Column(name = "fine_id", updatable = false, nullable = false) + @Column(updatable = false, nullable = false) private int fineId; /** diff --git a/src/main/java/com/libraryman_api/member/MemberController.java b/src/main/java/com/libraryman_api/member/MemberController.java index 664c175..8fa7d76 100644 --- a/src/main/java/com/libraryman_api/member/MemberController.java +++ b/src/main/java/com/libraryman_api/member/MemberController.java @@ -19,7 +19,7 @@ * This controller provides endpoints for performing CRUD operations on members. */ @RestController -@RequestMapping("/api/members") +@RequestMapping("/api") public class MemberController { private final MemberService memberService; @@ -42,7 +42,7 @@ public MemberController(MemberService memberService) { * @return a {@link Page} of {@link Members} representing all members in the library. * The results are sorted by name by default and limited to 5 members per page. */ - @GetMapping + @GetMapping("/get-all-members") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public Page getAllMembers(@PageableDefault(page = 0, size = 5, sort = "name") Pageable pageable, @RequestParam(required = false) String sortBy, @@ -69,7 +69,7 @@ public Page getAllMembers(@PageableDefault(page = 0, size = 5, sort * @param id the ID of the member to retrieve * @return a {@link ResponseEntity} containing the found {@link Members} object */ - @GetMapping("/{id}") + @GetMapping("/get-member-by-id/{id}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public ResponseEntity getMemberById(@PathVariable int id) { return memberService.getMemberById(id) @@ -85,7 +85,7 @@ public ResponseEntity getMemberById(@PathVariable int id) { * @param membersDtoDetails the {@link Members} object containing the updated details * @return the updated {@link Members} object */ - @PutMapping("/{id}") + @PutMapping("/update-member-by-id/{id}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN') or (hasRole('USER') and #id == authentication.principal.memberId)") public MembersDto updateMember(@PathVariable int id, @Valid @RequestBody UpdateMembersDto membersDtoDetails) { return memberService.updateMember(id, membersDtoDetails); @@ -97,7 +97,7 @@ public MembersDto updateMember(@PathVariable int id, @Valid @RequestBody UpdateM * * @param id the ID of the member to delete */ - @DeleteMapping("/{id}") + @DeleteMapping("/delete-member-by-id/{id}") @PreAuthorize("hasRole('LIBRARIAN') or hasRole('ADMIN')") public void deleteMember(@PathVariable int id) { memberService.deleteMember(id); @@ -111,7 +111,7 @@ public void deleteMember(@PathVariable int id) { * @param updatePasswordDto the {@link UpdatePasswordDto} object containing the password details * @return a {@link ResponseEntity} containing a success message indicating the password was updated successfully */ - @PutMapping("/{id}/password") + @PutMapping("/update-password-by-id/{id}") @PreAuthorize("#id == authentication.principal.memberId") public ResponseEntity updatePassword(@PathVariable int id, @Valid @RequestBody UpdatePasswordDto updatePasswordDto) { diff --git a/src/main/java/com/libraryman_api/newsletter/NewsletterController.java b/src/main/java/com/libraryman_api/newsletter/NewsletterController.java index c1cbc8b..960bb1d 100644 --- a/src/main/java/com/libraryman_api/newsletter/NewsletterController.java +++ b/src/main/java/com/libraryman_api/newsletter/NewsletterController.java @@ -20,22 +20,21 @@ public ResponseEntity subscribe(@RequestParam String email) { try { String result = newsletterService.subscribe(email); - switch (result) { - case "Invalid email format.": - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result); // 400 Bad Request + return switch (result) { + case "Invalid email format." -> + ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result); // 400 Bad Request - case "Email is already subscribed.": - return ResponseEntity.status(HttpStatus.CONFLICT).body(result); // 409 Conflict + case "Email is already subscribed." -> + ResponseEntity.status(HttpStatus.CONFLICT).body(result); // 409 Conflict - case "You have successfully subscribed!": - return ResponseEntity.status(HttpStatus.CREATED).body(result); // 201 Created + case "You have successfully subscribed!" -> + ResponseEntity.status(HttpStatus.CREATED).body(result); // 201 Created - case "You have successfully re-subscribed!": - return ResponseEntity.status(HttpStatus.OK).body(result); // 200 OK + case "You have successfully re-subscribed!" -> + ResponseEntity.status(HttpStatus.OK).body(result); // 200 OK - default: - return ResponseEntity.status(HttpStatus.OK).body(result); // Default 200 OK - } + default -> ResponseEntity.status(HttpStatus.OK).body(result); // Default 200 OK + }; } catch (Exception e) { // Handle unexpected errors return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) @@ -49,19 +48,18 @@ public ResponseEntity unsubscribe(@RequestParam String token) { try { String result = newsletterService.unsubscribe(token); - switch (result) { - case "Invalid or expired token.": - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(result); // 404 Not Found + return switch (result) { + case "Invalid or expired token." -> + ResponseEntity.status(HttpStatus.NOT_FOUND).body(result); // 404 Not Found - case "You are already unsubscribed.": - return ResponseEntity.status(HttpStatus.CONFLICT).body(result); // 409 Conflict + case "You are already unsubscribed." -> + ResponseEntity.status(HttpStatus.CONFLICT).body(result); // 409 Conflict - case "You have successfully unsubscribed!": - return ResponseEntity.status(HttpStatus.OK).body(result); // 200 OK + case "You have successfully unsubscribed!" -> + ResponseEntity.status(HttpStatus.OK).body(result); // 200 OK - default: - return ResponseEntity.status(HttpStatus.OK).body(result); // Default 200 OK - } + default -> ResponseEntity.status(HttpStatus.OK).body(result); // Default 200 OK + }; } catch (Exception e) { // Handle unexpected errors return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) diff --git a/src/main/java/com/libraryman_api/security/config/WebConfiguration.java b/src/main/java/com/libraryman_api/security/config/WebConfiguration.java index b10232c..daf1fb0 100644 --- a/src/main/java/com/libraryman_api/security/config/WebConfiguration.java +++ b/src/main/java/com/libraryman_api/security/config/WebConfiguration.java @@ -40,9 +40,11 @@ public SecurityFilterChain web(HttpSecurity http) throws Exception { .requestMatchers("/api/signup").permitAll() .requestMatchers("/api/login").permitAll() .requestMatchers("/api/logout").permitAll() - .requestMatchers("/api/books").permitAll() + .requestMatchers("/api/get-all-books/**").permitAll() + .requestMatchers("/api/book/search**").permitAll() .requestMatchers("/api/analytics/**").hasAnyRole("ADMIN", "LIBRARIAN") // New line for analytics .anyRequest().authenticated() + ) .logout(logout -> logout .deleteCookies("LibraryManCookie")) diff --git a/src/main/java/com/libraryman_api/security/services/SignupService.java b/src/main/java/com/libraryman_api/security/services/SignupService.java index 4d6b0e8..5c0a4c4 100644 --- a/src/main/java/com/libraryman_api/security/services/SignupService.java +++ b/src/main/java/com/libraryman_api/security/services/SignupService.java @@ -34,12 +34,18 @@ public void signup(Members members) { } String encoded_password = passwordEncoder.bCryptPasswordEncoder().encode(members.getPassword()); Members new_members = new Members(); - new_members.setEmail(members.getEmail()); + +// TODO: check for proper username format + new_members.setUsername(members.getUsername()); + new_members.setName(members.getName()); - new_members.setPassword(encoded_password); + +// TODO: check for proper email format + new_members.setEmail(members.getEmail()); + new_members.setRole(Role.USER); new_members.setMembershipDate(new Date()); - new_members.setUsername(members.getUsername()); + new_members.setPassword(encoded_password); memberRepository.save(new_members); }