138 lines
5.8 KiB
Java
138 lines
5.8 KiB
Java
package app.mealsmadeeasy.api.image;
|
|
|
|
import app.mealsmadeeasy.api.image.body.ImageUpdateBody;
|
|
import app.mealsmadeeasy.api.image.converter.ImageToViewConverter;
|
|
import app.mealsmadeeasy.api.image.spec.ImageCreateSpec;
|
|
import app.mealsmadeeasy.api.image.spec.ImageUpdateSpec;
|
|
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 lombok.RequiredArgsConstructor;
|
|
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")
|
|
@RequiredArgsConstructor
|
|
public class ImageController {
|
|
|
|
private final ImageService imageService;
|
|
private final UserService userService;
|
|
private final ImageToViewConverter imageToViewConverter;
|
|
|
|
private ImageUpdateSpec getImageUpdateSpec(ImageUpdateBody body) {
|
|
final var builder = ImageUpdateSpec.builder()
|
|
.alt(body.getAlt())
|
|
.caption(body.getCaption())
|
|
.isPublic(body.getIsPublic())
|
|
.clearAllViewers(body.getClearAllViewers());
|
|
if (body.getViewersToAdd() != null) {
|
|
builder.viewersToAdd(body.getViewersToAdd().stream()
|
|
.map(this.userService::getUser)
|
|
.collect(Collectors.toSet())
|
|
);
|
|
}
|
|
if (body.getViewersToRemove() != null) {
|
|
builder.viewersToRemove(body.getViewersToRemove().stream()
|
|
.map(this.userService::getUser)
|
|
.collect(Collectors.toSet())
|
|
);
|
|
}
|
|
return builder.build();
|
|
}
|
|
|
|
@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 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 {
|
|
final var specBuilder = ImageCreateSpec.builder()
|
|
.alt(alt)
|
|
.caption(caption)
|
|
.isPublic(isPublic);
|
|
|
|
if (viewers != null) {
|
|
specBuilder.viewersToAdd(viewers.stream().map(this.userService::getUser).collect(Collectors.toSet()));
|
|
}
|
|
final Image saved = this.imageService.create(
|
|
principal,
|
|
filename,
|
|
image.getInputStream(),
|
|
image.getSize(),
|
|
specBuilder.build()
|
|
);
|
|
return ResponseEntity.status(201).body(this.imageToViewConverter.convert(saved, principal, true));
|
|
}
|
|
|
|
@PostMapping("/{username}/{filename}")
|
|
public ResponseEntity<ImageView> updateInfo(
|
|
@AuthenticationPrincipal User principal,
|
|
@PathVariable String username,
|
|
@PathVariable String filename,
|
|
@RequestBody ImageUpdateBody body
|
|
) {
|
|
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.imageToViewConverter.convert(updated, principal, true));
|
|
}
|
|
|
|
@DeleteMapping("/{username}/{filename}")
|
|
public ResponseEntity<Object> deleteImage(
|
|
@AuthenticationPrincipal User principal,
|
|
@PathVariable String username,
|
|
@PathVariable String filename
|
|
) throws IOException {
|
|
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();
|
|
}
|
|
|
|
}
|