ADD user authentication checks for clip access

This commit is contained in:
2025-07-23 00:00:45 +02:00
parent 87ad7e3537
commit f6e6aae5c6
5 changed files with 65 additions and 38 deletions

View File

@@ -8,12 +8,10 @@ import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import com.ddf.vodsystem.exceptions.NotAuthenticated;
import com.ddf.vodsystem.repositories.ClipRepository;
import com.ddf.vodsystem.security.CustomOAuth2User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
@@ -24,15 +22,18 @@ public class ClipService {
private final MetadataService metadataService;
private final DirectoryService directoryService;
private final FfmpegService ffmpegService;
private final UserService userService;
public ClipService(ClipRepository clipRepository,
MetadataService metadataService,
DirectoryService directoryService,
FfmpegService ffmpegService) {
FfmpegService ffmpegService,
UserService userService) {
this.clipRepository = clipRepository;
this.metadataService = metadataService;
this.directoryService = directoryService;
this.ffmpegService = ffmpegService;
this.userService = userService;
}
/**
@@ -53,7 +54,7 @@ public class ClipService {
Float fileSize = metadataService.getFileSize(job.getOutputFile());
job.getOutputVideoMetadata().setFileSize(fileSize);
User user = getUser();
User user = userService.getUser();
if (user != null) {
persistClip(job.getOutputVideoMetadata(), user, job);
}
@@ -63,7 +64,7 @@ public class ClipService {
}
public List<Clip> getClipsByUser() {
User user = getUser();
User user = userService.getUser();
if (user == null) {
logger.warn("No authenticated user found");
@@ -73,14 +74,31 @@ public class ClipService {
return clipRepository.findByUser(user);
}
private User getUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof CustomOAuth2User oAuth2user) {
return oAuth2user.getUser();
public Clip getClipById(Long id) {
Clip clip = clipRepository.findById(id).orElse(null);
if (clip == null) {
logger.warn("Clip with ID {} not found", id);
return null;
}
return null;
if (!isAuthenticatedForClip(clip)) {
logger.warn("User is not authorized to access clip with ID {}", id);
throw new NotAuthenticated("You are not authorized to access this clip");
}
return clip;
}
public boolean isAuthenticatedForClip(Clip clip) {
User user = userService.getUser();
if (user == null || clip == null) {
return false;
}
return user.getId().equals(clip.getUser().getId());
}
private void persistClip(VideoMetadata videoMetadata, User user, Job job) {
// Move clip from temp to output directory
String fileExtension = directoryService.getFileExtension(job.getOutputFile().getAbsolutePath());
@@ -114,8 +132,4 @@ public class ClipService {
clip.setThumbnailPath(thumbnailOutputFile.getPath());
clipRepository.save(clip);
}
public Clip getClipById(Long id) {
return clipRepository.findById(id).orElse(null);
}
}

View File

@@ -42,25 +42,6 @@ public class DirectoryService {
return new File(dir);
}
public File getOutputFile(String id, String extension) {
if (id == null || id.length() < 2) {
throw new IllegalArgumentException("ID must be at least 2 characters long");
}
// Create subdirectories from first 2 characters of the ID
String shard1 = id.substring(0, 2);
String shard2 = id.substring(2);
String dir = outputDir +
File.separator +
shard1 +
File.separator +
shard2 +
(extension.isEmpty() ? "" : "." + extension);
return new File(dir);
}
public File getUserClipsDir(Long userId) {
if (userId == null) {
throw new IllegalArgumentException("User ID cannot be null");

View File

@@ -5,6 +5,7 @@ import com.ddf.vodsystem.entities.JobStatus;
import com.ddf.vodsystem.exceptions.JobNotFinished;
import com.ddf.vodsystem.exceptions.JobNotFound;
import com.ddf.vodsystem.entities.Job;
import com.ddf.vodsystem.exceptions.NotAuthenticated;
import com.ddf.vodsystem.repositories.ClipRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
@@ -18,11 +19,15 @@ public class DownloadService {
private final JobService jobService;
private final ClipRepository clipRepository;
private final ClipService clipService;
@Autowired
public DownloadService(JobService jobService, ClipRepository clipRepository) {
public DownloadService(JobService jobService,
ClipRepository clipRepository,
ClipService clipService) {
this.jobService = jobService;
this.clipRepository = clipRepository;
this.clipService = clipService;
}
public Resource downloadInput(String uuid) {
@@ -52,8 +57,13 @@ public class DownloadService {
}
public Resource downloadClip(Clip clip) {
if (!clipService.isAuthenticatedForClip(clip)) {
throw new NotAuthenticated("Not authenticated for this clip");
}
String path = clip.getVideoPath();
File file = new File(path);
if (!file.exists()) {
throw new JobNotFound("Clip file not found");
}
@@ -67,6 +77,10 @@ public class DownloadService {
}
public Resource downloadThumbnail(Clip clip) {
if (!clipService.isAuthenticatedForClip(clip)) {
throw new NotAuthenticated("Not authenticated for this clip thumbnail");
}
String path = clip.getThumbnailPath();
File file = new File(path);
if (!file.exists()) {

View File

@@ -48,13 +48,13 @@ public class FfmpegService {
runWithProgress(inputFile, outputFile, videoMetadata, new AtomicReference<>(0f));
}
public void generateThumbnail(File inputFile, File outputFile, Float time) throws IOException, InterruptedException {
logger.info("Generating thumbnail at {} seconds", time);
public void generateThumbnail(File inputFile, File outputFile, Float timeInVideo) throws IOException, InterruptedException {
logger.info("Generating thumbnail at {} seconds", timeInVideo);
List<String> command = new ArrayList<>();
command.add("ffmpeg");
command.add("-ss");
command.add(time.toString());
command.add(timeInVideo.toString());
command.add("-i");
command.add(inputFile.getAbsolutePath());
command.add("-frames:v");

View File

@@ -0,0 +1,18 @@
package com.ddf.vodsystem.services;
import com.ddf.vodsystem.entities.User;
import com.ddf.vodsystem.security.CustomOAuth2User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public User getUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated() && auth.getPrincipal() instanceof CustomOAuth2User oAuth2user) {
return oAuth2user.getUser();
}
return null;
}
}