docs(bruno): overhaul bruno to match new API
This commit is contained in:
@@ -1,30 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Get Google Token
|
|
||||||
type: http
|
|
||||||
seq: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url:
|
|
||||||
body: none
|
|
||||||
auth: oauth2
|
|
||||||
}
|
|
||||||
|
|
||||||
auth:oauth2 {
|
|
||||||
grant_type: authorization_code
|
|
||||||
callback_url: http://localhost:8080
|
|
||||||
authorization_url: https://accounts.google.com/o/oauth2/v2/auth
|
|
||||||
access_token_url: https://oauth2.googleapis.com/token
|
|
||||||
refresh_token_url:
|
|
||||||
client_id: {{google_client_id}}
|
|
||||||
client_secret: {{google_secret}}
|
|
||||||
scope: profile email openid
|
|
||||||
state:
|
|
||||||
pkce: true
|
|
||||||
credentials_placement: body
|
|
||||||
credentials_id: credentials
|
|
||||||
token_placement: header
|
|
||||||
token_header_prefix: Bearer
|
|
||||||
auto_fetch_token: true
|
|
||||||
auto_refresh_token: false
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Get User
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/auth/user
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Login
|
|
||||||
type: http
|
|
||||||
seq: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
url: {{base_url}}/auth/login
|
|
||||||
body: json
|
|
||||||
auth: none
|
|
||||||
}
|
|
||||||
|
|
||||||
body:json {
|
|
||||||
{
|
|
||||||
"token": "{{$oauth2.credentials.id_token}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
script:post-response {
|
|
||||||
bru.setEnvVar("token", res.getBody().data.token);
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
meta {
|
meta {
|
||||||
name: Get all clips
|
name: Get all clips
|
||||||
type: http
|
type: http
|
||||||
seq: 1
|
seq: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
meta {
|
meta {
|
||||||
name: Update Clip
|
name: Update Clip
|
||||||
type: http
|
type: http
|
||||||
seq: 2
|
seq: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
patch {
|
patch {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
meta {
|
meta {
|
||||||
name: Clips
|
name: Clips
|
||||||
|
seq: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
auth {
|
auth {
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Converted Download
|
|
||||||
type: http
|
|
||||||
seq: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/download/output/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Original Download
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/download/input/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Download
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Edit
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
url: {{base_url}}/edit/{{uuid}}
|
|
||||||
body: formUrlEncoded
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
|
|
||||||
body:form-urlencoded {
|
|
||||||
startPoint: 10
|
|
||||||
duration: 40
|
|
||||||
title: best possible title
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Process
|
|
||||||
type: http
|
|
||||||
seq: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/process/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Progress
|
|
||||||
type: http
|
|
||||||
seq: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/progress/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Edit
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Converted Metadata
|
|
||||||
type: http
|
|
||||||
seq: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/metadata/converted/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Original Metadata
|
|
||||||
type: http
|
|
||||||
seq: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
get {
|
|
||||||
url: {{base_url}}/metadata/original/{{uuid}}
|
|
||||||
body: none
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Metadata
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Save Clip
|
|
||||||
type: http
|
|
||||||
seq: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
url: {{base_url}}/stream/clip
|
|
||||||
body: json
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
|
|
||||||
body:json {
|
|
||||||
{
|
|
||||||
"duration": 60
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
settings {
|
|
||||||
encodeUrl: true
|
|
||||||
timeout: 0
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
meta {
|
|
||||||
name: Save Section
|
|
||||||
type: http
|
|
||||||
seq: 2
|
|
||||||
}
|
|
||||||
|
|
||||||
post {
|
|
||||||
url: {{base_url}}/stream/save
|
|
||||||
body: json
|
|
||||||
auth: inherit
|
|
||||||
}
|
|
||||||
|
|
||||||
body:json {
|
|
||||||
{
|
|
||||||
"startTime": "2026-06-20T15:00:00Z",
|
|
||||||
"endTime": "2026-06-20T15:01:00Z"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
settings {
|
|
||||||
encodeUrl: true
|
|
||||||
timeout: 0
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
meta {
|
meta {
|
||||||
name: Streams
|
name: Streams
|
||||||
seq: 7
|
seq: 6
|
||||||
}
|
}
|
||||||
|
|
||||||
auth {
|
auth {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
meta {
|
meta {
|
||||||
name: Upload
|
name: Upload
|
||||||
type: http
|
type: http
|
||||||
seq: 1
|
seq: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
post {
|
||||||
|
|||||||
@@ -30,11 +30,9 @@ public class SecurityConfig {
|
|||||||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
.authorizeHttpRequests(auth -> auth
|
.authorizeHttpRequests(auth -> auth
|
||||||
.requestMatchers(HttpMethod.OPTIONS, "/api/v1/**").permitAll()
|
.requestMatchers(HttpMethod.OPTIONS, "/api/v1/**").permitAll()
|
||||||
.requestMatchers("/api/v1/download/clip/**","/api/v1/clips/", "/api/v1/clips/**").authenticated()
|
.requestMatchers("/api/v1/media/**").authenticated()
|
||||||
.requestMatchers("/api/v1/auth/login", "/api/v1/auth/user").permitAll()
|
.requestMatchers("/api/v1/jobs/**").authenticated()
|
||||||
.requestMatchers("/api/v1/upload", "/api/v1/download/**").permitAll()
|
.requestMatchers("/api/v1/users/me", "/api/v1/users/logout").authenticated()
|
||||||
.requestMatchers("/api/v1/edit/**", "/api/v1/process/**", "/api/v1/progress/**", "/api/v1/convert/**").permitAll()
|
|
||||||
.requestMatchers("/api/v1/metadata/**").permitAll()
|
|
||||||
.requestMatchers("/api/v1/stream/start", "/api/v1/stream/stop", "/api/v1/stream/heartbeat").permitAll()
|
.requestMatchers("/api/v1/stream/start", "/api/v1/stream/stop", "/api/v1/stream/heartbeat").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.ddf.vodsystem.controllers;
|
|||||||
import com.ddf.vodsystem.controllers.dto.JobResponse;
|
import com.ddf.vodsystem.controllers.dto.JobResponse;
|
||||||
import com.ddf.vodsystem.dto.APIResponse;
|
import com.ddf.vodsystem.dto.APIResponse;
|
||||||
import com.ddf.vodsystem.dto.Job;
|
import com.ddf.vodsystem.dto.Job;
|
||||||
|
import com.ddf.vodsystem.exceptions.ClipNotFound;
|
||||||
import com.ddf.vodsystem.exceptions.NotReadyException;
|
import com.ddf.vodsystem.exceptions.NotReadyException;
|
||||||
import com.ddf.vodsystem.services.JobRegistryService;
|
import com.ddf.vodsystem.services.JobRegistryService;
|
||||||
import org.springframework.core.io.FileSystemResource;
|
import org.springframework.core.io.FileSystemResource;
|
||||||
@@ -17,7 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api/v1/job")
|
@RequestMapping("api/v1/jobs")
|
||||||
public class JobController {
|
public class JobController {
|
||||||
private final JobRegistryService jobRegistryService;
|
private final JobRegistryService jobRegistryService;
|
||||||
private static final String SUCCESS = "success";
|
private static final String SUCCESS = "success";
|
||||||
@@ -57,7 +58,7 @@ public class JobController {
|
|||||||
Resource resource = new FileSystemResource(job.getDownload());
|
Resource resource = new FileSystemResource(job.getDownload());
|
||||||
|
|
||||||
if (!resource.exists()) {
|
if (!resource.exists()) {
|
||||||
return ResponseEntity.notFound().build();
|
throw new ClipNotFound("Job download file " + job.getDownload() + " does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
package com.ddf.vodsystem.controllers;
|
package com.ddf.vodsystem.controllers;
|
||||||
|
|
||||||
|
import com.ddf.vodsystem.controllers.dto.ClipSectionRequest;
|
||||||
|
import com.ddf.vodsystem.controllers.dto.SaveSectionRequest;
|
||||||
import com.ddf.vodsystem.controllers.dto.UUIDResponse;
|
import com.ddf.vodsystem.controllers.dto.UUIDResponse;
|
||||||
import com.ddf.vodsystem.dto.Job;
|
import com.ddf.vodsystem.dto.Job;
|
||||||
import com.ddf.vodsystem.dto.ClipOptions;
|
import com.ddf.vodsystem.dto.ClipOptions;
|
||||||
import com.ddf.vodsystem.dto.APIResponse;
|
import com.ddf.vodsystem.dto.APIResponse;
|
||||||
import com.ddf.vodsystem.services.MediaService;
|
import com.ddf.vodsystem.services.MediaService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/media")
|
@RequestMapping("/api/v1/media")
|
||||||
@@ -22,10 +25,10 @@ public class MediaController {
|
|||||||
this.mediaService = mediaService;
|
this.mediaService = mediaService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/compress")
|
@PostMapping(value = "/compress", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||||
public ResponseEntity<APIResponse<UUIDResponse>> compress(
|
public ResponseEntity<APIResponse<UUIDResponse>> compress(
|
||||||
@RequestParam("file")MultipartFile file,
|
@RequestParam("file")MultipartFile file,
|
||||||
@RequestParam("options") ClipOptions options
|
@Valid @ModelAttribute ClipOptions options
|
||||||
) throws IOException, InterruptedException {
|
) throws IOException, InterruptedException {
|
||||||
Job job = mediaService.compress(file, options);
|
Job job = mediaService.compress(file, options);
|
||||||
return ResponseEntity.ok(new APIResponse<>(
|
return ResponseEntity.ok(new APIResponse<>(
|
||||||
@@ -38,9 +41,8 @@ public class MediaController {
|
|||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
public ResponseEntity<APIResponse<UUIDResponse>> save(
|
public ResponseEntity<APIResponse<UUIDResponse>> save(
|
||||||
@RequestParam("start") Instant startTime,
|
@RequestBody SaveSectionRequest saveSectionRequest) throws IOException {
|
||||||
@RequestParam("end") Instant endTime) throws IOException {
|
Job job = mediaService.saveSection(saveSectionRequest.startTime(), saveSectionRequest.endTime());
|
||||||
Job job = mediaService.saveSection(startTime, endTime);
|
|
||||||
return ResponseEntity.ok(new APIResponse<>(
|
return ResponseEntity.ok(new APIResponse<>(
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
"Section saving successfully started",
|
"Section saving successfully started",
|
||||||
@@ -50,8 +52,8 @@ public class MediaController {
|
|||||||
|
|
||||||
@PostMapping("/clip")
|
@PostMapping("/clip")
|
||||||
public ResponseEntity<APIResponse<UUIDResponse>> clip(
|
public ResponseEntity<APIResponse<UUIDResponse>> clip(
|
||||||
@RequestParam("duration") float duration) throws IOException {
|
@RequestBody ClipSectionRequest clipSectionRequest) throws IOException {
|
||||||
Job job = mediaService.clip(duration);
|
Job job = mediaService.clip(clipSectionRequest.duration());
|
||||||
return ResponseEntity.ok(new APIResponse<>(
|
return ResponseEntity.ok(new APIResponse<>(
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
"Clipping successfully started",
|
"Clipping successfully started",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/user/")
|
@RequestMapping("/api/v1/users")
|
||||||
public class UserController {
|
public class UserController {
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
package com.ddf.vodsystem.dto;
|
package com.ddf.vodsystem.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ClipOptions {
|
public class ClipOptions {
|
||||||
|
@NotBlank
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Positive
|
||||||
private Float startPoint;
|
private Float startPoint;
|
||||||
|
|
||||||
|
@NotNull @Positive
|
||||||
private Float duration;
|
private Float duration;
|
||||||
|
|
||||||
|
@DecimalMin("1.0") @DecimalMax("120.0")
|
||||||
private Float fps;
|
private Float fps;
|
||||||
|
|
||||||
|
@Positive
|
||||||
private Integer width;
|
private Integer width;
|
||||||
|
|
||||||
|
@Positive
|
||||||
private Integer height;
|
private Integer height;
|
||||||
|
|
||||||
|
@Positive
|
||||||
private Float fileSize;
|
private Float fileSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
@@ -60,9 +61,12 @@ public class JwtFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Optional<Authentication> authentication = getAuthentication(jwt);
|
Optional<Authentication> authentication = getAuthentication(jwt);
|
||||||
authentication.ifPresent(value ->
|
authentication.ifPresent(auth -> {
|
||||||
SecurityContextHolder.getContext().setAuthentication(value)
|
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||||
);
|
context.setAuthentication(auth);
|
||||||
|
SecurityContextHolder.setContext(context);
|
||||||
|
});
|
||||||
|
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public class ClipService {
|
|||||||
try {
|
try {
|
||||||
newClipFile = directoryService.getUserClipsFile(user.getId(), fileName);
|
newClipFile = directoryService.getUserClipsFile(user.getId(), fileName);
|
||||||
thumbnailFile = directoryService.getUserThumbnailsFile(user.getId(), fileName + ".png");
|
thumbnailFile = directoryService.getUserThumbnailsFile(user.getId(), fileName + ".png");
|
||||||
directoryService.cutFile(clipFile, newClipFile);
|
directoryService.copyFile(clipFile, newClipFile);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new StorageException("Failed to move clip from temporary directory to output directory", e);
|
throw new StorageException("Failed to move clip from temporary directory to output directory", e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user