Skip to content

Commit 6b7b0c0

Browse files
authored
Refactor/314 (#333)
* Feat : uuid를 갖는 로우 존재확인하는 JPA메서드 추가 * Feat : 데이터베이스에 uuid를 갖는 로우 존재확인하는 메서드 추가 * Feat : uuid와 해상도를 전달하면 해상도를 검사하고 적절한 mpd파일을 반환하는 PresignedGetObjectRequest를 요청하도록 수정 * Chore : 패키지 변경 * Test/Chore : 테스트 추가, 업로드요청 모두 허용하던부분 수정
1 parent cd192a5 commit 6b7b0c0

File tree

9 files changed

+124
-7
lines changed

9 files changed

+124
-7
lines changed

back/src/main/java/com/back/domain/file/video/controller/VideoController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public RsData<UploadUrlGetResponse> getUploadUrl(@RequestParam String filename)
3737

3838
@GetMapping("/videos/download")
3939
@Operation(summary = "다운로드용 URL 요청", description = "파일 다운로드를 위한 Presigned URL을 발급받습니다.")
40-
public RsData<DownLoadUrlGetResponse> getDownloadUrls(@RequestParam String objectKey) {
41-
PresignedUrlResponse downloadUrl = fileManager.getDownloadUrl(objectKey);
40+
public RsData<DownLoadUrlGetResponse> getDownloadUrls(@RequestParam String uuid, @RequestParam String resolution) {
41+
PresignedUrlResponse downloadUrl = fileManager.getDownloadUrl(uuid, resolution);
4242
DownLoadUrlGetResponse response = new DownLoadUrlGetResponse(downloadUrl.url().toString(), downloadUrl.expiresAt());
4343
return new RsData<>("200", "다운로드용 URL 요청완료", response);
4444
}

back/src/main/java/com/back/domain/file/video/repository/VideoRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
@Repository
1010
public interface VideoRepository extends JpaRepository<Video, Integer> {
1111
Optional<Video> findByUuid(String uuid);
12+
boolean existsByUuid(String uuid);
1213
}

back/src/main/java/com/back/domain/file/video/service/FileManager.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88

99
import java.net.URL;
1010
import java.time.LocalDateTime;
11+
import java.util.Set;
1112
import java.util.UUID;
1213

1314
@Service
1415
@RequiredArgsConstructor
1516
public class FileManager {
1617
private final VideoService videoService;
1718
private final S3Service s3Service;
19+
private final Set<String> validResolutions = Set.of("480p", "720p", "1080p");
1820

1921
public PresignedUrlResponse getUploadUrl(String filename) {
2022
String contentType = validateAndGetContentType(filename);
@@ -53,8 +55,11 @@ private String validateAndGetContentType(String filename) {
5355
}
5456
}
5557

56-
public PresignedUrlResponse getDownloadUrl(String objectKey) {
58+
public PresignedUrlResponse getDownloadUrl(String uuid, String resolution) {
5759
Integer expires = 60;
60+
validateResolution(resolution);
61+
videoService.isExistByUuid(uuid);
62+
String objectKey = "transcoded/videos/" + uuid + "/" + resolution + "/manifest.mpd";
5863
URL url = s3Service.generateDownloadUrl(objectKey, expires);
5964
LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(expires);
6065
return new PresignedUrlResponse(url, expiresAt);
@@ -68,4 +73,10 @@ public void updateVideoStatus(String videoId, String status) {
6873
videoService.createVideo(videoId, status, "/", 0);
6974
}
7075
}
76+
77+
public void validateResolution(String resolution) {
78+
if (!validResolutions.contains(resolution)) {
79+
throw new ServiceException("400", "지원하지 않는 해상도입니다: " + resolution);
80+
}
81+
}
7182
}

back/src/main/java/com/back/domain/file/video/service/VideoService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,10 @@ public Video updateStatus(String uuid, String status) {
2929
news.updateStatus(status);
3030
return videoRepository.save(news);
3131
}
32+
33+
public void isExistByUuid(String uuid) {
34+
if (!videoRepository.existsByUuid(uuid)) {
35+
throw new ServiceException("404", "Video not found");
36+
}
37+
}
3238
}

back/src/main/java/com/back/global/security/SecurityConfig.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
3030
.requestMatchers("/auth/**").permitAll()
3131
.requestMatchers("/actuator/**").permitAll()
3232
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**").permitAll()
33-
.requestMatchers("/videos/upload").permitAll()
3433
.requestMatchers("/ws-chat/**").permitAll()
3534
.anyRequest().authenticated()
3635
)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.back.domain.file.video.controller;
2+
3+
import com.back.domain.file.video.dto.service.PresignedUrlResponse;
4+
import com.back.domain.file.video.service.FileManager;
5+
import org.junit.jupiter.api.DisplayName;
6+
import org.junit.jupiter.api.Test;
7+
import org.mockito.Mockito;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
10+
import org.springframework.boot.test.context.SpringBootTest;
11+
import org.springframework.http.MediaType;
12+
import org.springframework.security.test.context.support.WithMockUser;
13+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
14+
import org.springframework.test.web.servlet.MockMvc;
15+
16+
import java.net.URL;
17+
import java.time.LocalDateTime;
18+
19+
import static org.mockito.ArgumentMatchers.anyString;
20+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
21+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
22+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
23+
24+
@SpringBootTest
25+
@AutoConfigureMockMvc
26+
class VideoControllerTest {
27+
28+
@Autowired
29+
private MockMvc mockMvc;
30+
31+
@MockitoBean
32+
private FileManager fileManager;
33+
34+
@Test
35+
@DisplayName("업로드 URL 요청 - 성공")
36+
@WithMockUser(roles = "ADMIN")
37+
void testGetUploadUrl() throws Exception {
38+
URL mockUrl = new URL("https://bucket.s3.amazonaws.com/123e4567-e89b-12d3-a456-426614174000");
39+
LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(10);
40+
41+
Mockito.when(fileManager.getUploadUrl(anyString()))
42+
.thenReturn(new PresignedUrlResponse(mockUrl, expiresAt));
43+
44+
mockMvc.perform(get("/videos/upload")
45+
.param("filename", "test.mp4")
46+
.contentType(MediaType.APPLICATION_JSON))
47+
.andExpect(status().isOk())
48+
.andExpect(jsonPath("$.resultCode").value("200"))
49+
.andExpect(jsonPath("$.msg").value("업로드용 URL 요청완료"))
50+
.andExpect(jsonPath("$.data.url").value(mockUrl.toString()))
51+
.andExpect(jsonPath("$.data.uuid").value("123e4567-e89b-12d3-a456-426614174000"));
52+
}
53+
54+
@Test
55+
@DisplayName("업로드 URL 요청 - 권한 부족")
56+
@WithMockUser(roles = "USER")
57+
// ADMIN 아님
58+
void testGetUploadUrl_Unauthorized() throws Exception {
59+
mockMvc.perform(get("/videos/upload")
60+
.param("filename", "test.mp4")
61+
.contentType(MediaType.APPLICATION_JSON))
62+
.andExpect(status().isForbidden()); // 403 권한 부족
63+
}
64+
65+
@Test
66+
@DisplayName("업로드 URL 요청 - 파일명에 확장자가 없는 경우")
67+
@WithMockUser(roles = "ADMIN")
68+
void testGetUploadUrl_NoExtension() throws Exception {
69+
Mockito.when(fileManager.getUploadUrl(anyString()))
70+
.thenThrow(new com.back.global.exception.ServiceException("400", "지원하지 않는 동영상 파일 형식입니다: testfile"));
71+
72+
mockMvc.perform(get("/videos/upload")
73+
.param("filename", "testfile")
74+
.contentType(MediaType.APPLICATION_JSON))
75+
.andExpect(status().isBadRequest())
76+
.andExpect(jsonPath("$.resultCode").value("400"))
77+
.andExpect(jsonPath("$.msg").value("지원하지 않는 동영상 파일 형식입니다: testfile"));
78+
}
79+
80+
@Test
81+
@DisplayName("다운로드 URL 요청 - 성공")
82+
@WithMockUser
83+
void testGetDownloadUrls() throws Exception {
84+
URL mockUrl = new URL("https://bucket.s3.amazonaws.com/test.mp4");
85+
LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(10);
86+
87+
Mockito.when(fileManager.getDownloadUrl(anyString(), anyString()))
88+
.thenReturn(new PresignedUrlResponse(mockUrl, expiresAt));
89+
90+
mockMvc.perform(get("/videos/download")
91+
.param("uuid", "123e4567-e89b-12d3-a456-426614174000")
92+
.param("resolution", "1080p")
93+
.contentType(MediaType.APPLICATION_JSON))
94+
.andExpect(status().isOk())
95+
.andExpect(jsonPath("$.resultCode").value("200"))
96+
.andExpect(jsonPath("$.msg").value("다운로드용 URL 요청완료"))
97+
.andExpect(jsonPath("$.data.url").value(mockUrl.toString()));
98+
}
99+
100+
}

back/src/test/java/com/back/domain/file/entity/VideoTest.java renamed to back/src/test/java/com/back/domain/file/video/entity/VideoTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.back.domain.file.entity;
1+
package com.back.domain.file.video.entity;
22

33
import com.back.domain.file.video.entity.Video;
44
import org.junit.jupiter.api.DisplayName;

back/src/test/java/com/back/domain/file/service/S3ServiceTest.java renamed to back/src/test/java/com/back/domain/file/video/service/S3ServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.back.domain.file.service;
1+
package com.back.domain.file.video.service;
22

33
import com.back.domain.file.video.service.S3Service;
44
import com.back.global.exception.ServiceException;

back/src/test/java/com/back/domain/file/service/VideoServiceTest.java renamed to back/src/test/java/com/back/domain/file/video/service/VideoServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.back.domain.file.service;
1+
package com.back.domain.file.video.service;
22

33
import com.back.domain.file.video.entity.Video;
44
import com.back.domain.file.video.repository.VideoRepository;

0 commit comments

Comments
 (0)