s3 bucket integration for image storage

This commit is contained in:
Adrien
2026-04-04 13:26:55 +02:00
parent 5acfdd33c1
commit b154e29f2d
9 changed files with 195 additions and 91 deletions
@@ -1,25 +1,37 @@
package com.aiteacher.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.aiteacher.figure.FigureStorageService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import java.nio.file.Paths;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class FigureStorageConfig implements WebMvcConfigurer {
/**
* Serves figure images by redirecting to a presigned S3 URL.
* The key stored in DB is the full S3 object key, e.g. "figures/{bookId}/{figureId}.png".
*/
@RestController
@RequestMapping("/api/v1/figures")
public class FigureStorageConfig {
private final String basePath;
private final FigureStorageService figureStorageService;
public FigureStorageConfig(@Value("${app.figure-storage.base-path:./uploads}") String basePath) {
this.basePath = Paths.get(basePath).toAbsolutePath().normalize().toString();
public FigureStorageConfig(FigureStorageService figureStorageService) {
this.figureStorageService = figureStorageService;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Serve GET /api/v1/figures/** from the local file store
registry.addResourceHandler("/api/v1/figures/**")
.addResourceLocations("file:" + basePath + "/figures/");
@GetMapping("/{bookId}/{filename}")
public void serve(@PathVariable String bookId,
@PathVariable String filename,
HttpServletResponse response) throws IOException {
String key = "figures/" + bookId + "/" + filename;
try {
String url = figureStorageService.presignedUrl(key);
response.sendRedirect(url);
} catch (Exception ex) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Figure not found: " + key);
}
}
}
@@ -20,7 +20,9 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/figures/**").permitAll()
.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults())
.csrf(AbstractHttpConfigurer::disable);
return http.build();