meals-made-easy-api/src/main/java/app/mealsmadeeasy/api/image/ImageController.java
2024-07-29 17:09:03 -05:00

149 lines
6.2 KiB
Java

package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.image.body.ImageUpdateInfoBody;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.image.spec.ImageUpdateInfoSpec;
import app.mealsmadeeasy.api.image.view.ImageView;
import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserService;
import app.mealsmadeeasy.api.util.AccessDeniedView;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authorization.AuthorizationDeniedException;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/images")
public class ImageController {
private final ImageService imageService;
private final UserService userService;
public ImageController(ImageService imageService, UserService userService) {
this.imageService = imageService;
this.userService = userService;
}
private ImageUpdateInfoSpec getImageUpdateSpec(ImageUpdateInfoBody body) {
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setAlt(body.getAlt());
spec.setCaption(body.getCaption());
spec.setPublic(body.getPublic());
if (body.getViewersToAdd() != null) {
spec.setViewersToAdd(
body.getViewersToAdd().stream()
.map(this.userService::getUser)
.collect(Collectors.toSet())
);
}
if (body.getViewersToRemove() != null) {
spec.setViewersToRemove(
body.getViewersToRemove().stream()
.map(this.userService::getUser)
.collect(Collectors.toSet())
);
}
spec.setClearAllViewers(body.getClearAllViewers());
return spec;
}
@ExceptionHandler
public ResponseEntity<AccessDeniedView> onAccessDenied(AccessDeniedException e) {
if (e instanceof AuthorizationDeniedException) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.contentType(MediaType.APPLICATION_JSON)
.body(new AccessDeniedView(HttpStatus.FORBIDDEN.value(), e.getMessage()));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.contentType(MediaType.APPLICATION_JSON)
.body(new AccessDeniedView(HttpStatus.UNAUTHORIZED.value(), e.getMessage()));
}
}
@GetMapping("/{username}/{filename}")
public ResponseEntity<InputStreamResource> getImage(
@AuthenticationPrincipal User principal,
@PathVariable String username,
@PathVariable String filename
) throws ImageException, IOException {
final User owner = this.userService.getUser(username);
final Image image = this.imageService.getByOwnerAndFilename(owner, filename, principal);
final InputStream imageInputStream = this.imageService.getImageContent(image, principal);
return ResponseEntity.status(200)
.contentType(MediaType.parseMediaType(image.getMimeType()))
.body(new InputStreamResource(imageInputStream));
}
@PutMapping
public ResponseEntity<ImageView> putImage(
@RequestParam MultipartFile image,
@RequestParam String filename,
@RequestParam(required = false) String alt,
@RequestParam(required = false) String caption,
@RequestParam(required = false) Boolean isPublic,
@RequestParam(required = false) Set<String> viewers,
@AuthenticationPrincipal User principal
) throws IOException, ImageException {
if (principal == null) {
throw new AccessDeniedException("Must be logged in.");
}
final ImageCreateInfoSpec createSpec = new ImageCreateInfoSpec();
createSpec.setAlt(alt);
createSpec.setCaption(caption);
createSpec.setPublic(isPublic);
if (viewers != null) {
createSpec.setViewersToAdd(viewers.stream().map(this.userService::getUser).collect(Collectors.toSet()));
}
final Image saved = this.imageService.create(
principal,
filename,
image.getInputStream(),
image.getSize(),
createSpec
);
return ResponseEntity.status(201).body(this.imageService.toImageView(saved));
}
@PostMapping("/{username}/{filename}")
public ResponseEntity<ImageView> updateInfo(
@AuthenticationPrincipal User principal,
@PathVariable String username,
@PathVariable String filename,
@RequestBody ImageUpdateInfoBody body
) throws ImageException {
if (principal == null) {
throw new AccessDeniedException("Must be logged in.");
}
final User owner = this.userService.getUser(username);
final Image image = this.imageService.getByOwnerAndFilename(owner, filename, principal);
final Image updated = this.imageService.update(image, principal, this.getImageUpdateSpec(body));
return ResponseEntity.ok(this.imageService.toImageView(updated));
}
@DeleteMapping("/{username}/{filename}")
public ResponseEntity<Object> deleteImage(
@AuthenticationPrincipal User principal,
@PathVariable String username,
@PathVariable String filename
) throws ImageException, IOException {
if (principal == null) {
throw new AccessDeniedException("Must be logged in.");
}
final User owner = this.userService.getUser(username);
final Image image = this.imageService.getByOwnerAndFilename(owner, filename, principal);
this.imageService.deleteImage(image, principal);
return ResponseEntity.noContent().build();
}
}