From 6433294ced788b4b6c774d53709746999e34400e Mon Sep 17 00:00:00 2001 From: ThisBirchWood Date: Tue, 12 Aug 2025 15:39:06 +0200 Subject: [PATCH] REFACTOR code to use Optional entity --- frontend/src/components/Dropdown.tsx | 6 +- .../vodsystem/controllers/ClipController.java | 7 +- .../vodsystem/controllers/UserController.java | 8 +- .../com/ddf/vodsystem/security/JwtFilter.java | 56 +++++----- .../ddf/vodsystem/services/ClipService.java | 103 ++++++++++++------ .../vodsystem/services/DirectoryService.java | 2 +- .../ddf/vodsystem/services/UserService.java | 13 +-- 7 files changed, 121 insertions(+), 74 deletions(-) diff --git a/frontend/src/components/Dropdown.tsx b/frontend/src/components/Dropdown.tsx index 34f2113..4be7738 100644 --- a/frontend/src/components/Dropdown.tsx +++ b/frontend/src/components/Dropdown.tsx @@ -9,7 +9,9 @@ type DropdownItemProps = { const DropdownItem = ({ item, onClick, className }: DropdownItemProps) => { return ( -
  • onClick(item)}> +
  • onClick(item)} + > {item}
  • ); @@ -30,7 +32,7 @@ const Dropdown = ({ label, children, className }: DropdownProps) => { }; useEffect(() => { - function handleClickOutside(event: { target: any; }) { + function handleClickOutside(event: { target: any }) { if (ref.current && !ref.current.contains(event.target)) { setIsOpen(false); } diff --git a/src/main/java/com/ddf/vodsystem/controllers/ClipController.java b/src/main/java/com/ddf/vodsystem/controllers/ClipController.java index e340c8d..7f5b506 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/ClipController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/ClipController.java @@ -11,6 +11,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Optional; @RestController @RequestMapping("/api/v1/clips") @@ -35,12 +36,12 @@ public class ClipController { @GetMapping("/{id}") public ResponseEntity> getClipById(@PathVariable Long id) { - Clip clip = clipService.getClipById(id); - if (clip == null) { + Optional clip = clipService.getClipById(id); + if (clip.isEmpty()) { return ResponseEntity.notFound().build(); } - ClipDTO clipDTO = convertToDTO(clip); + ClipDTO clipDTO = convertToDTO(clip.get()); return ResponseEntity.ok( new APIResponse<>("success", "Clip retrieved successfully", clipDTO) diff --git a/src/main/java/com/ddf/vodsystem/controllers/UserController.java b/src/main/java/com/ddf/vodsystem/controllers/UserController.java index 9a095c7..b01ed53 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/UserController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/UserController.java @@ -10,6 +10,8 @@ import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.Optional; + @RestController @RequestMapping("/api/v1/auth/") public class UserController { @@ -21,14 +23,14 @@ public class UserController { @GetMapping("/user") public ResponseEntity> user() { - User user = userService.getLoggedInUser(); + Optional user = userService.getLoggedInUser(); - if (user == null) { + if (user.isEmpty()) { throw new NotAuthenticated("User not authenticated"); } return ResponseEntity.ok( - new APIResponse<>("success", "User retrieved successfully", user) + new APIResponse<>("success", "User retrieved successfully", user.get()) ); } diff --git a/src/main/java/com/ddf/vodsystem/security/JwtFilter.java b/src/main/java/com/ddf/vodsystem/security/JwtFilter.java index 6c4e72f..1af18e2 100644 --- a/src/main/java/com/ddf/vodsystem/security/JwtFilter.java +++ b/src/main/java/com/ddf/vodsystem/security/JwtFilter.java @@ -1,7 +1,6 @@ package com.ddf.vodsystem.security; import com.ddf.vodsystem.entities.User; -import com.ddf.vodsystem.exceptions.NotAuthenticated; import com.ddf.vodsystem.services.UserService; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; @@ -20,6 +19,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.util.Arrays; import java.util.List; +import java.util.Optional; @Component public class JwtFilter extends OncePerRequestFilter { @@ -59,32 +59,34 @@ public class JwtFilter extends OncePerRequestFilter { } } - if (jwt == null) { - logger.debug("No JWT found in request"); - filterChain.doFilter(request, response); - return; - } - - logger.debug("JWT found in request"); - Long userId = jwtService.validateTokenAndGetUserId(jwt); - - if (userId == null) { - logger.warn("Invalid JWT: {}", jwt); - filterChain.doFilter(request, response); - return; - } - - User user; - try { - user = userService.getUserById(userId); - } catch (NotAuthenticated e) { - filterChain.doFilter(request, response); - return; - } - - Authentication authentication = new UsernamePasswordAuthenticationToken(user, jwt, List.of(new SimpleGrantedAuthority("ROLE_USER"))); - SecurityContextHolder.getContext().setAuthentication(authentication); - + Optional authentication = getAuthentication(jwt); + authentication.ifPresent(value -> + SecurityContextHolder.getContext().setAuthentication(value) + ); filterChain.doFilter(request, response); } + + private Optional getAuthentication(String jwt) { + if (jwt == null || jwt.isEmpty()) { + return Optional.empty(); + } + + Long userId = jwtService.validateTokenAndGetUserId(jwt); + if (userId == null) { + return Optional.empty(); + } + + Optional user = userService.getUserById(userId); + if (user.isEmpty()) { + return Optional.empty(); + } + + Authentication authentication = new UsernamePasswordAuthenticationToken( + user.get(), + jwt, + List.of(new SimpleGrantedAuthority("ROLE_USER")) + ); + + return Optional.of(authentication); + } } diff --git a/src/main/java/com/ddf/vodsystem/services/ClipService.java b/src/main/java/com/ddf/vodsystem/services/ClipService.java index d49ea2b..b8c8700 100644 --- a/src/main/java/com/ddf/vodsystem/services/ClipService.java +++ b/src/main/java/com/ddf/vodsystem/services/ClipService.java @@ -8,6 +8,7 @@ import java.io.File; import java.io.IOException; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutionException; import com.ddf.vodsystem.exceptions.FFMPEGException; @@ -60,42 +61,56 @@ public class ClipService { * @throws InterruptedException if the thread is interrupted during processing. */ public void create(VideoMetadata inputMetadata, - VideoMetadata outputMetadata, - File inputFile, - File outputFile, - ProgressTracker progress) + VideoMetadata outputMetadata, + File inputFile, + File outputFile, + ProgressTracker progress) throws IOException, InterruptedException { - User user = userService.getLoggedInUser(); + Optional user = userService.getLoggedInUser(); metadataService.normalizeVideoMetadata(inputMetadata, outputMetadata); compressionService.compress(inputFile, outputFile, outputMetadata, progress) - .thenRun(() -> { - if (user != null) { - persistClip(outputMetadata, user, outputFile, inputFile.getName()); - } - }); + .thenRun(() -> user.ifPresent(value -> + persistClip( + outputMetadata, + value, + outputFile, + inputFile.getName() + ))); } + /** + * Retrieves all clips associated with the currently logged-in user. + * + * @return a list of clips belonging to the authenticated user. + * @throws NotAuthenticated if the user is not authenticated. + */ public List getClipsByUser() { - User user = userService.getLoggedInUser(); + Optional user = userService.getLoggedInUser(); - if (user == null) { - logger.warn("No authenticated user found"); - return List.of(); + if (user.isEmpty()) { + throw new NotAuthenticated("User is not authenticated"); } - return clipRepository.findByUser(user); + return clipRepository.findByUser(user.get()); } - public Clip getClipById(Long id) { - Clip clip = clipRepository.findById(id).orElse(null); + /** + * Retrieves a clip by its ID, ensuring the user is authenticated to access it. + * + * @param id the ID of the clip to retrieve. + * @return an Optional containing the Clip if found and accessible, or empty if not found. + * @throws NotAuthenticated if the user is not authorized to access the clip. + */ + public Optional getClipById(Long id) { + Optional clip = clipRepository.findById(id); - if (clip == null) { + if (clip.isEmpty()) { logger.warn("Clip with ID {} not found", id); - return null; + return clip; } - if (!isAuthenticatedForClip(clip)) { + if (!isAuthenticatedForClip(clip.get())) { logger.warn("User is not authorized to access clip with ID {}", id); throw new NotAuthenticated("You are not authorized to access this clip"); } @@ -103,34 +118,44 @@ public class ClipService { return clip; } + /** + * Deletes a clip by its ID, ensuring the user is authenticated to perform the deletion. + * + * @param id the ID of the clip to delete. + * @return true if the clip was successfully deleted, false if it was not found. + * @throws NotAuthenticated if the user is not authorized to delete the clip. + */ public boolean deleteClip(Long id) { - Clip clip = getClipById(id); - if (clip == null) { + Optional possibleClip = getClipById(id); + if (possibleClip.isEmpty()) { logger.warn("Clip with ID {} not found for deletion", id); return false; } + Clip clip = possibleClip.get(); if (!isAuthenticatedForClip(clip)) { - logger.warn("User is not authorized to delete clip with ID {}", id); throw new NotAuthenticated("You are not authorized to delete this clip"); } - File clipFile = new File(clip.getVideoPath()); - File thumbnailFile = new File(clip.getThumbnailPath()); - directoryService.deleteFile(clipFile); - directoryService.deleteFile(thumbnailFile); - + deleteClipFiles(clip); clipRepository.delete(clip); + logger.info("Clip with ID {} deleted successfully", id); return true; } + /** + * Checks if the currently logged-in user is authenticated to access the specified clip. + * + * @param clip the clip to check access for. + * @return true if the user is authenticated for the clip, false otherwise. + */ public boolean isAuthenticatedForClip(Clip clip) { - User user = userService.getLoggedInUser(); - if (user == null || clip == null) { + Optional user = userService.getLoggedInUser(); + if (user.isEmpty() || clip == null) { return false; } - return user.getId().equals(clip.getUser().getId()); + return user.get().getId().equals(clip.getUser().getId()); } private void persistClip(VideoMetadata videoMetadata, @@ -175,4 +200,20 @@ public class ClipService { logger.info("Clip created successfully with ID: {}", clip.getId()); } + + private void deleteClipFiles(Clip clip) { + File clipFile = new File(clip.getVideoPath()); + File thumbnailFile = new File(clip.getThumbnailPath()); + + boolean clipDeleted = directoryService.deleteFile(clipFile); + boolean thumbnailDeleted = directoryService.deleteFile(thumbnailFile); + + if (!clipDeleted) { + throw new FFMPEGException("Failed to delete clip file: " + clipFile.getAbsolutePath()); + } + + if (!thumbnailDeleted) { + throw new FFMPEGException("Failed to delete thumbnail file: " + thumbnailFile.getAbsolutePath()); + } + } } diff --git a/src/main/java/com/ddf/vodsystem/services/DirectoryService.java b/src/main/java/com/ddf/vodsystem/services/DirectoryService.java index 64252c5..2b23515 100644 --- a/src/main/java/com/ddf/vodsystem/services/DirectoryService.java +++ b/src/main/java/com/ddf/vodsystem/services/DirectoryService.java @@ -118,7 +118,7 @@ public class DirectoryService { try { Files.delete(file.toPath()); - logger.info("Deleted file: {}", file.getAbsolutePath()); + logger.debug("Deleted file: {}", file.getAbsolutePath()); return true; } catch (IOException e) { logger.error("Error deleting file: {}", e.getMessage()); diff --git a/src/main/java/com/ddf/vodsystem/services/UserService.java b/src/main/java/com/ddf/vodsystem/services/UserService.java index 7dc2032..5c63d80 100644 --- a/src/main/java/com/ddf/vodsystem/services/UserService.java +++ b/src/main/java/com/ddf/vodsystem/services/UserService.java @@ -41,17 +41,16 @@ public class UserService { this.jwtService = jwtService; } - public User getUserById(Long userId) { - return userRepository.findById(userId) - .orElseThrow(() -> new NotAuthenticated("User not found")); + public Optional getUserById(Long userId) { + return userRepository.findById(userId); } - public User getLoggedInUser() { + public Optional getLoggedInUser() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof User) { - return (User) auth.getPrincipal(); + if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof User user) { + return Optional.of(user); } - return null; + return Optional.empty(); } public String login(String idToken) {