REFACTOR code to use Optional entity
This commit is contained in:
@@ -9,7 +9,9 @@ type DropdownItemProps = {
|
|||||||
|
|
||||||
const DropdownItem = ({ item, onClick, className }: DropdownItemProps) => {
|
const DropdownItem = ({ item, onClick, className }: DropdownItemProps) => {
|
||||||
return (
|
return (
|
||||||
<li className={clsx(className, "cursor-pointer hover:bg-gray-100 px-4 py-2 align-middle")} onClick={() => onClick(item)}>
|
<li className={clsx(className, "cursor-pointer hover:bg-gray-100 px-4 py-2 align-middle")}
|
||||||
|
onClick={() => onClick(item)}
|
||||||
|
>
|
||||||
{item}
|
{item}
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
@@ -30,7 +32,7 @@ const Dropdown = ({ label, children, className }: DropdownProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleClickOutside(event: { target: any; }) {
|
function handleClickOutside(event: { target: any }) {
|
||||||
if (ref.current && !ref.current.contains(event.target)) {
|
if (ref.current && !ref.current.contains(event.target)) {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/clips")
|
@RequestMapping("/api/v1/clips")
|
||||||
@@ -35,12 +36,12 @@ public class ClipController {
|
|||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public ResponseEntity<APIResponse<ClipDTO>> getClipById(@PathVariable Long id) {
|
public ResponseEntity<APIResponse<ClipDTO>> getClipById(@PathVariable Long id) {
|
||||||
Clip clip = clipService.getClipById(id);
|
Optional<Clip> clip = clipService.getClipById(id);
|
||||||
if (clip == null) {
|
if (clip.isEmpty()) {
|
||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipDTO clipDTO = convertToDTO(clip);
|
ClipDTO clipDTO = convertToDTO(clip.get());
|
||||||
|
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
new APIResponse<>("success", "Clip retrieved successfully", clipDTO)
|
new APIResponse<>("success", "Clip retrieved successfully", clipDTO)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import org.springframework.http.ResponseCookie;
|
|||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/auth/")
|
@RequestMapping("/api/v1/auth/")
|
||||||
public class UserController {
|
public class UserController {
|
||||||
@@ -21,14 +23,14 @@ public class UserController {
|
|||||||
|
|
||||||
@GetMapping("/user")
|
@GetMapping("/user")
|
||||||
public ResponseEntity<APIResponse<User>> user() {
|
public ResponseEntity<APIResponse<User>> user() {
|
||||||
User user = userService.getLoggedInUser();
|
Optional<User> user = userService.getLoggedInUser();
|
||||||
|
|
||||||
if (user == null) {
|
if (user.isEmpty()) {
|
||||||
throw new NotAuthenticated("User not authenticated");
|
throw new NotAuthenticated("User not authenticated");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok(
|
return ResponseEntity.ok(
|
||||||
new APIResponse<>("success", "User retrieved successfully", user)
|
new APIResponse<>("success", "User retrieved successfully", user.get())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ddf.vodsystem.security;
|
package com.ddf.vodsystem.security;
|
||||||
|
|
||||||
import com.ddf.vodsystem.entities.User;
|
import com.ddf.vodsystem.entities.User;
|
||||||
import com.ddf.vodsystem.exceptions.NotAuthenticated;
|
|
||||||
import com.ddf.vodsystem.services.UserService;
|
import com.ddf.vodsystem.services.UserService;
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@@ -20,6 +19,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class JwtFilter extends OncePerRequestFilter {
|
public class JwtFilter extends OncePerRequestFilter {
|
||||||
@@ -59,32 +59,34 @@ public class JwtFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jwt == null) {
|
Optional<Authentication> authentication = getAuthentication(jwt);
|
||||||
logger.debug("No JWT found in request");
|
authentication.ifPresent(value ->
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(value)
|
||||||
|
);
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("JWT found in request");
|
private Optional<Authentication> getAuthentication(String jwt) {
|
||||||
|
if (jwt == null || jwt.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
Long userId = jwtService.validateTokenAndGetUserId(jwt);
|
Long userId = jwtService.validateTokenAndGetUserId(jwt);
|
||||||
|
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
logger.warn("Invalid JWT: {}", jwt);
|
return Optional.empty();
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User user;
|
Optional<User> user = userService.getUserById(userId);
|
||||||
try {
|
if (user.isEmpty()) {
|
||||||
user = userService.getUserById(userId);
|
return Optional.empty();
|
||||||
} catch (NotAuthenticated e) {
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Authentication authentication = new UsernamePasswordAuthenticationToken(user, jwt, List.of(new SimpleGrantedAuthority("ROLE_USER")));
|
Authentication authentication = new UsernamePasswordAuthenticationToken(
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
user.get(),
|
||||||
|
jwt,
|
||||||
|
List.of(new SimpleGrantedAuthority("ROLE_USER"))
|
||||||
|
);
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
return Optional.of(authentication);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import com.ddf.vodsystem.exceptions.FFMPEGException;
|
import com.ddf.vodsystem.exceptions.FFMPEGException;
|
||||||
@@ -66,36 +67,50 @@ public class ClipService {
|
|||||||
ProgressTracker progress)
|
ProgressTracker progress)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
|
|
||||||
User user = userService.getLoggedInUser();
|
Optional<User> user = userService.getLoggedInUser();
|
||||||
metadataService.normalizeVideoMetadata(inputMetadata, outputMetadata);
|
metadataService.normalizeVideoMetadata(inputMetadata, outputMetadata);
|
||||||
compressionService.compress(inputFile, outputFile, outputMetadata, progress)
|
compressionService.compress(inputFile, outputFile, outputMetadata, progress)
|
||||||
.thenRun(() -> {
|
.thenRun(() -> user.ifPresent(value ->
|
||||||
if (user != null) {
|
persistClip(
|
||||||
persistClip(outputMetadata, user, outputFile, inputFile.getName());
|
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<Clip> getClipsByUser() {
|
public List<Clip> getClipsByUser() {
|
||||||
User user = userService.getLoggedInUser();
|
Optional<User> user = userService.getLoggedInUser();
|
||||||
|
|
||||||
if (user == null) {
|
if (user.isEmpty()) {
|
||||||
logger.warn("No authenticated user found");
|
throw new NotAuthenticated("User is not authenticated");
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<Clip> getClipById(Long id) {
|
||||||
|
Optional<Clip> clip = clipRepository.findById(id);
|
||||||
|
|
||||||
if (clip == null) {
|
if (clip.isEmpty()) {
|
||||||
logger.warn("Clip with ID {} not found", id);
|
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);
|
logger.warn("User is not authorized to access clip with ID {}", id);
|
||||||
throw new NotAuthenticated("You are not authorized to access this clip");
|
throw new NotAuthenticated("You are not authorized to access this clip");
|
||||||
}
|
}
|
||||||
@@ -103,34 +118,44 @@ public class ClipService {
|
|||||||
return clip;
|
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) {
|
public boolean deleteClip(Long id) {
|
||||||
Clip clip = getClipById(id);
|
Optional<Clip> possibleClip = getClipById(id);
|
||||||
if (clip == null) {
|
if (possibleClip.isEmpty()) {
|
||||||
logger.warn("Clip with ID {} not found for deletion", id);
|
logger.warn("Clip with ID {} not found for deletion", id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Clip clip = possibleClip.get();
|
||||||
if (!isAuthenticatedForClip(clip)) {
|
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");
|
throw new NotAuthenticated("You are not authorized to delete this clip");
|
||||||
}
|
}
|
||||||
|
|
||||||
File clipFile = new File(clip.getVideoPath());
|
deleteClipFiles(clip);
|
||||||
File thumbnailFile = new File(clip.getThumbnailPath());
|
|
||||||
directoryService.deleteFile(clipFile);
|
|
||||||
directoryService.deleteFile(thumbnailFile);
|
|
||||||
|
|
||||||
clipRepository.delete(clip);
|
clipRepository.delete(clip);
|
||||||
|
|
||||||
logger.info("Clip with ID {} deleted successfully", id);
|
logger.info("Clip with ID {} deleted successfully", id);
|
||||||
return true;
|
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) {
|
public boolean isAuthenticatedForClip(Clip clip) {
|
||||||
User user = userService.getLoggedInUser();
|
Optional<User> user = userService.getLoggedInUser();
|
||||||
if (user == null || clip == null) {
|
if (user.isEmpty() || clip == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return user.getId().equals(clip.getUser().getId());
|
return user.get().getId().equals(clip.getUser().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void persistClip(VideoMetadata videoMetadata,
|
private void persistClip(VideoMetadata videoMetadata,
|
||||||
@@ -175,4 +200,20 @@ public class ClipService {
|
|||||||
|
|
||||||
logger.info("Clip created successfully with ID: {}", clip.getId());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ public class DirectoryService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Files.delete(file.toPath());
|
Files.delete(file.toPath());
|
||||||
logger.info("Deleted file: {}", file.getAbsolutePath());
|
logger.debug("Deleted file: {}", file.getAbsolutePath());
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("Error deleting file: {}", e.getMessage());
|
logger.error("Error deleting file: {}", e.getMessage());
|
||||||
|
|||||||
@@ -41,17 +41,16 @@ public class UserService {
|
|||||||
this.jwtService = jwtService;
|
this.jwtService = jwtService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getUserById(Long userId) {
|
public Optional<User> getUserById(Long userId) {
|
||||||
return userRepository.findById(userId)
|
return userRepository.findById(userId);
|
||||||
.orElseThrow(() -> new NotAuthenticated("User not found"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getLoggedInUser() {
|
public Optional<User> getLoggedInUser() {
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof User) {
|
if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof User user) {
|
||||||
return (User) auth.getPrincipal();
|
return Optional.of(user);
|
||||||
}
|
}
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String login(String idToken) {
|
public String login(String idToken) {
|
||||||
|
|||||||
Reference in New Issue
Block a user