ImageController updateInfo and deleteImage methods and related. A bunch of TODO tests.

This commit is contained in:
Jesse Brault 2024-07-26 10:12:14 -05:00
parent 9976b7337f
commit a5c0add82b
9 changed files with 378 additions and 111 deletions

View File

@ -2,6 +2,8 @@ package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.auth.AuthService; import app.mealsmadeeasy.api.auth.AuthService;
import app.mealsmadeeasy.api.auth.LoginException; import app.mealsmadeeasy.api.auth.LoginException;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.image.spec.ImageUpdateInfoSpec;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserCreateException; import app.mealsmadeeasy.api.user.UserCreateException;
import app.mealsmadeeasy.api.user.UserService; import app.mealsmadeeasy.api.user.UserService;
@ -21,8 +23,10 @@ import org.testcontainers.utility.DockerImageName;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Set;
import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@ -76,7 +80,8 @@ public class ImageControllerTests {
owner, owner,
USER_FILENAME, USER_FILENAME,
hal9000, hal9000,
27881L 27881L,
new ImageCreateInfoSpec()
); );
} }
} }
@ -89,12 +94,24 @@ public class ImageControllerTests {
} }
} }
private Image makePublic(Image image, User modifier) {
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setPublic(true);
return this.imageService.update(image, modifier, spec);
}
private Image addViewer(Image image, User modifier, User viewerToAdd) {
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setViewersToAdd(Set.of(viewerToAdd));
return this.imageService.update(image, modifier, spec);
}
@Test @Test
@DirtiesContext @DirtiesContext
public void getImageNoPrincipal() throws Exception { public void getImageNoPrincipal() throws Exception {
final User owner = this.createTestUser("imageOwner"); final User owner = this.createTestUser("imageOwner");
final Image image = this.createHal9000(owner); final Image image = this.createHal9000(owner);
this.imageService.setPublic(image, owner, true); this.makePublic(image, owner);
try (final InputStream hal9000 = getHal9000()) { try (final InputStream hal9000 = getHal9000()) {
final byte[] halBytes = hal9000.readAllBytes(); final byte[] halBytes = hal9000.readAllBytes();
this.mockMvc.perform(get("/images/imageOwner/HAL9000.svg")) this.mockMvc.perform(get("/images/imageOwner/HAL9000.svg"))
@ -130,7 +147,7 @@ public class ImageControllerTests {
final User owner = this.createTestUser("imageOwner"); final User owner = this.createTestUser("imageOwner");
final User viewer = this.createTestUser("viewer"); final User viewer = this.createTestUser("viewer");
final Image image = this.createHal9000(owner); final Image image = this.createHal9000(owner);
this.imageService.addViewer(image, owner, viewer); this.addViewer(image, owner, viewer);
final String accessToken = this.getAccessToken(viewer.getUsername()); final String accessToken = this.getAccessToken(viewer.getUsername());
this.doGetImageTestWithViewer(accessToken); this.doGetImageTestWithViewer(accessToken);
} }
@ -170,4 +187,58 @@ public class ImageControllerTests {
} }
} }
@Test
@DirtiesContext
public void updateAlt() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void updateCaption() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void updateIsPublic() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void addViewers() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void removeViewers() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void clearAllViewers() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void updateInfoWithViewerFails() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void deleteImageWithOwner() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void deleteImageWithViewer() throws Exception {
fail("TODO");
}
} }

View File

@ -1,5 +1,7 @@
package app.mealsmadeeasy.api.image; package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.image.spec.ImageUpdateInfoSpec;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserCreateException; import app.mealsmadeeasy.api.user.UserCreateException;
import app.mealsmadeeasy.api.user.UserService; import app.mealsmadeeasy.api.user.UserService;
@ -17,6 +19,7 @@ import org.testcontainers.utility.DockerImageName;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.Set;
import static app.mealsmadeeasy.api.image.ContainsImagesMatcher.containsImages; import static app.mealsmadeeasy.api.image.ContainsImagesMatcher.containsImages;
import static app.mealsmadeeasy.api.user.IsUserMatcher.isUser; import static app.mealsmadeeasy.api.user.IsUserMatcher.isUser;
@ -25,6 +28,7 @@ import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.junit.jupiter.api.Assertions.fail;
@Testcontainers @Testcontainers
@SpringBootTest @SpringBootTest
@ -68,11 +72,18 @@ public class S3ImageServiceTests {
owner, owner,
USER_FILENAME, USER_FILENAME,
hal9000, hal9000,
27881L 27881L,
new ImageCreateInfoSpec()
); );
} }
} }
private Image makePublic(Image image, User modifier) {
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setPublic(true);
return this.imageService.update(image, modifier, spec);
}
@Test @Test
public void smokeScreen() {} public void smokeScreen() {}
@ -109,7 +120,7 @@ public class S3ImageServiceTests {
public void loadPublicImage() throws ImageException, IOException { public void loadPublicImage() throws ImageException, IOException {
final User owner = this.createTestUser("imageOwner"); final User owner = this.createTestUser("imageOwner");
Image image = this.createHal9000(owner); Image image = this.createHal9000(owner);
image = this.imageService.setPublic(image, owner, true); image = this.makePublic(image, owner);
try (final InputStream stored = try (final InputStream stored =
this.imageService.getImageContent(image, null)) { this.imageService.getImageContent(image, null)) {
final byte[] storedBytes = stored.readAllBytes(); final byte[] storedBytes = stored.readAllBytes();
@ -123,7 +134,9 @@ public class S3ImageServiceTests {
final User owner = this.createTestUser("imageOwner"); final User owner = this.createTestUser("imageOwner");
final User viewer = this.createTestUser("imageViewer"); final User viewer = this.createTestUser("imageViewer");
Image image = this.createHal9000(owner); Image image = this.createHal9000(owner);
image = this.imageService.addViewer(image, owner, viewer); final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setViewersToAdd(Set.of(viewer));
image = this.imageService.update(image, owner, spec);
try (final InputStream stored = try (final InputStream stored =
this.imageService.getImageContent(image, viewer)) { this.imageService.getImageContent(image, viewer)) {
final byte[] storedBytes = stored.readAllBytes(); final byte[] storedBytes = stored.readAllBytes();
@ -151,40 +164,44 @@ public class S3ImageServiceTests {
@Test @Test
@DirtiesContext @DirtiesContext
public void updateOwner() throws ImageException, IOException { public void updateAlt() throws Exception {
final User oldOwner = this.createTestUser("oldImageOwner"); fail("TODO");
final User newOwner = this.createTestUser("newImageOwner");
Image image = this.createHal9000(oldOwner);
assertThat(image.getOwner(), isUser(oldOwner));
image = this.imageService.updateOwner(image, oldOwner, newOwner);
assertThat(image.getOwner(), isUser(newOwner));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void setAlt() throws ImageException, IOException { public void updateCaption() throws Exception {
final User owner = this.createTestUser("imageOwner"); fail("TODO");
Image image = this.createHal9000(owner);
image = this.imageService.setAlt(image, owner, "Example alt.");
assertThat(image.getAlt(), is("Example alt."));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void setCaption() throws ImageException, IOException { public void updateIsPublic() throws Exception {
final User owner = this.createTestUser("imageOwner"); fail("TODO");
Image image = this.createHal9000(owner);
image = this.imageService.setCaption(image, owner, "Example caption.");
assertThat(image.getCaption(), is("Example caption."));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void setPublicToTrue() throws ImageException, IOException { public void addViewers() throws Exception {
final User owner = this.createTestUser("imageOwner"); fail("TODO");
Image image = this.createHal9000(owner); }
image = this.imageService.setPublic(image, owner, true);
assertThat(image.isPublic(), is(true)); @Test
@DirtiesContext
public void removeViewers() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void clearAllViewers() throws Exception {
fail("TODO");
}
@Test
@DirtiesContext
public void deleteImage() throws Exception {
fail("TODO");
} }
} }

View File

@ -3,6 +3,7 @@ package app.mealsmadeeasy.api;
import app.mealsmadeeasy.api.image.Image; import app.mealsmadeeasy.api.image.Image;
import app.mealsmadeeasy.api.image.ImageException; import app.mealsmadeeasy.api.image.ImageException;
import app.mealsmadeeasy.api.image.ImageService; import app.mealsmadeeasy.api.image.ImageService;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.recipe.Recipe; import app.mealsmadeeasy.api.recipe.Recipe;
import app.mealsmadeeasy.api.recipe.RecipeService; import app.mealsmadeeasy.api.recipe.RecipeService;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
@ -47,13 +48,15 @@ public class DevConfiguration {
logger.info("Created {}", recipe); logger.info("Created {}", recipe);
try (final InputStream inputStream = DevConfiguration.class.getResourceAsStream("HAL9000.svg")) { try (final InputStream inputStream = DevConfiguration.class.getResourceAsStream("HAL9000.svg")) {
final ImageCreateInfoSpec spec = new ImageCreateInfoSpec();
spec.setPublic(true);
final Image image = this.imageService.create( final Image image = this.imageService.create(
testUser, testUser,
"HAL9000.svg", "HAL9000.svg",
inputStream, inputStream,
27881L 27881L,
spec
); );
this.imageService.setPublic(image, testUser, true);
logger.info("Created {}", image); logger.info("Created {}", image);
} catch (IOException | ImageException e) { } catch (IOException | ImageException e) {
logger.error("Failed to load and/or create HAL9000.svg", e); logger.error("Failed to load and/or create HAL9000.svg", e);

View File

@ -1,5 +1,8 @@
package app.mealsmadeeasy.api.image; 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.image.view.ImageView;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserService; import app.mealsmadeeasy.api.user.UserService;
@ -14,6 +17,8 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Set;
import java.util.stream.Collectors;
@RestController @RestController
@RequestMapping("/images") @RequestMapping("/images")
@ -22,6 +27,7 @@ public class ImageController {
private static ImageView getView(Image image, User owner) { private static ImageView getView(Image image, User owner) {
final ImageView imageView = new ImageView(); final ImageView imageView = new ImageView();
imageView.setCreated(image.getCreated()); imageView.setCreated(image.getCreated());
imageView.setModified(image.getModified());
imageView.setFilename(image.getUserFilename()); imageView.setFilename(image.getUserFilename());
imageView.setMimeType(image.getMimeType()); imageView.setMimeType(image.getMimeType());
imageView.setAlt(image.getAlt()); imageView.setAlt(image.getAlt());
@ -44,6 +50,29 @@ public class ImageController {
this.userService = userService; 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;
}
@GetMapping("/{username}/{filename}") @GetMapping("/{username}/{filename}")
public ResponseEntity<InputStreamResource> getImage( public ResponseEntity<InputStreamResource> getImage(
@AuthenticationPrincipal User principal, @AuthenticationPrincipal User principal,
@ -65,29 +94,58 @@ public class ImageController {
@RequestParam(required = false) String alt, @RequestParam(required = false) String alt,
@RequestParam(required = false) String caption, @RequestParam(required = false) String caption,
@RequestParam(required = false) Boolean isPublic, @RequestParam(required = false) Boolean isPublic,
@RequestParam(required = false) Set<String> viewers,
@AuthenticationPrincipal User principal @AuthenticationPrincipal User principal
) throws IOException, ImageException { ) throws IOException, ImageException {
if (principal == null) { if (principal == null) {
throw new AccessDeniedException("Must be logged in."); throw new AccessDeniedException("Must be logged in.");
} }
final ImageCreateInfoSpec createSpec = new ImageCreateInfoSpec();
Image saved = this.imageService.create( 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, principal,
filename, filename,
image.getInputStream(), image.getInputStream(),
image.getSize() image.getSize(),
createSpec
); );
if (alt != null) {
saved = this.imageService.setAlt(saved, principal, alt);
}
if (caption != null) {
saved = this.imageService.setCaption(saved, principal, caption);
}
if (isPublic != null) {
saved = this.imageService.setPublic(saved, principal, isPublic);
}
return ResponseEntity.status(201).body(getView(saved, principal)); return ResponseEntity.status(201).body(getView(saved, principal));
} }
@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(getView(updated, owner));
}
@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();
}
} }

View File

@ -1,5 +1,7 @@
package app.mealsmadeeasy.api.image; package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.image.spec.ImageUpdateInfoSpec;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -9,23 +11,15 @@ import java.util.List;
public interface ImageService { public interface ImageService {
Image create(User owner, String userFilename, InputStream inputStream, long objectSize) Image create(User owner, String userFilename, InputStream inputStream, long objectSize, ImageCreateInfoSpec infoSpec)
throws IOException, ImageException; throws IOException, ImageException;
Image getByOwnerAndFilename(User owner, String filename, User viewer) throws ImageException; Image getByOwnerAndFilename(User owner, String filename, User viewer) throws ImageException;
InputStream getImageContent(Image image, @Nullable User viewer) throws IOException; InputStream getImageContent(Image image, @Nullable User viewer) throws IOException;
List<Image> getImagesOwnedBy(User user); List<Image> getImagesOwnedBy(User user);
Image updateOwner(Image image, User oldOwner, User newOwner); Image update(Image image, User modifier, ImageUpdateInfoSpec spec);
Image setAlt(Image image, User owner, String alt); void deleteImage(Image image, User modifier) throws IOException;
Image setCaption(Image image, User owner, String caption);
Image setPublic(Image image, User owner, boolean isPublic);
Image addViewer(Image image, User owner, User viewer);
Image removeViewer(Image image, User owner, User viewer);
Image clearViewers(Image image, User owner);
void deleteImage(Image image, User owner) throws IOException;
} }

View File

@ -1,5 +1,7 @@
package app.mealsmadeeasy.api.image; package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.image.spec.ImageCreateInfoSpec;
import app.mealsmadeeasy.api.image.spec.ImageUpdateInfoSpec;
import app.mealsmadeeasy.api.s3.S3Manager; import app.mealsmadeeasy.api.s3.S3Manager;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserEntity; import app.mealsmadeeasy.api.user.UserEntity;
@ -17,6 +19,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Service @Service
/* TODO: update modified LocalDateTime when updating */
public class S3ImageService implements ImageService { public class S3ImageService implements ImageService {
private static final Pattern extensionPattern = Pattern.compile(".+\\.(.+)$"); private static final Pattern extensionPattern = Pattern.compile(".+\\.(.+)$");
@ -62,9 +65,29 @@ public class S3ImageService implements ImageService {
}; };
} }
private void transferFromSpec(S3ImageEntity entity, ImageCreateInfoSpec spec) {
if (spec.getAlt() != null) {
entity.setAlt(spec.getAlt());
}
if (spec.getCaption() != null) {
entity.setCaption(spec.getCaption());
}
if (spec.getPublic() != null) {
entity.setPublic(spec.getPublic());
}
for (final User viewerToAdd : spec.getViewersToAdd()) {
entity.getViewers().add((UserEntity) viewerToAdd);
}
}
@Override @Override
public Image create(User owner, String userFilename, InputStream inputStream, long objectSize) public Image create(
throws IOException, ImageException { User owner,
String userFilename,
InputStream inputStream,
long objectSize,
ImageCreateInfoSpec createSpec
) throws IOException, ImageException {
final String mimeType = this.getMimeType(userFilename); final String mimeType = this.getMimeType(userFilename);
final String uuid = UUID.randomUUID().toString(); final String uuid = UUID.randomUUID().toString();
final String extension = this.getExtension(mimeType); final String extension = this.getExtension(mimeType);
@ -78,6 +101,7 @@ public class S3ImageService implements ImageService {
draft.setUserFilename(userFilename); draft.setUserFilename(userFilename);
draft.setMimeType(mimeType); draft.setMimeType(mimeType);
draft.setObjectName(objectName); draft.setObjectName(objectName);
this.transferFromSpec(draft, createSpec);
return this.imageRepository.save(draft); return this.imageRepository.save(draft);
} }
@ -103,64 +127,22 @@ public class S3ImageService implements ImageService {
} }
@Override @Override
@PreAuthorize("@imageSecurity.isOwner(#image, #oldOwner)") @PreAuthorize("@imageSecurity.isOwner(#image, #modifier)")
public Image updateOwner(Image image, User oldOwner, User newOwner) { public Image update(final Image image, User modifier, ImageUpdateInfoSpec updateSpec) {
final S3ImageEntity imageEntity = (S3ImageEntity) image; S3ImageEntity entity = (S3ImageEntity) image;
imageEntity.setOwner((UserEntity) newOwner); this.transferFromSpec(entity, updateSpec);
return this.imageRepository.save(imageEntity); for (final User toRemove : updateSpec.getViewersToRemove()) {
entity.getViewers().remove((UserEntity) toRemove);
}
if (updateSpec.getClearAllViewers() != null) {
entity.getViewers().clear();
}
return this.imageRepository.save(entity);
} }
@Override @Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)") @PreAuthorize("@imageSecurity.isOwner(#image, #modifier)")
public Image setAlt(Image image, User owner, String alt) { public void deleteImage(Image image, User modifier) throws IOException {
final S3ImageEntity imageEntity = (S3ImageEntity) image;
imageEntity.setAlt(alt);
return this.imageRepository.save(imageEntity);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public Image setCaption(Image image, User owner, String caption) {
final S3ImageEntity imageEntity = (S3ImageEntity) image;
imageEntity.setCaption(caption);
return this.imageRepository.save(imageEntity);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public Image setPublic(Image image, User owner, boolean isPublic) {
final S3ImageEntity imageEntity = (S3ImageEntity) image;
imageEntity.setPublic(isPublic);
return this.imageRepository.save(imageEntity);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public Image addViewer(Image image, User owner, User viewer) {
final S3ImageEntity withViewers = this.imageRepository.getByIdWithViewers(image.getId());
withViewers.getViewers().add((UserEntity) viewer);
return this.imageRepository.save(withViewers);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public Image removeViewer(Image image, User owner, User viewer) {
final S3ImageEntity withViewers = this.imageRepository.getByIdWithViewers(image.getId());
withViewers.getViewers().remove((UserEntity) viewer);
return this.imageRepository.save(withViewers);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public Image clearViewers(Image image, User owner) {
final S3ImageEntity withViewers = this.imageRepository.getByIdWithViewers(image.getId());
withViewers.getViewers().clear();
return this.imageRepository.save(withViewers);
}
@Override
@PreAuthorize("@imageSecurity.isOwner(#image, #owner)")
public void deleteImage(Image image, User owner) throws IOException {
final S3ImageEntity imageEntity = (S3ImageEntity) image; final S3ImageEntity imageEntity = (S3ImageEntity) image;
this.imageRepository.delete(imageEntity); this.imageRepository.delete(imageEntity);
this.s3Manager.delete("images", imageEntity.getObjectName()); this.s3Manager.delete("images", imageEntity.getObjectName());

View File

@ -0,0 +1,64 @@
package app.mealsmadeeasy.api.image.body;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class ImageUpdateInfoBody {
private @Nullable String alt;
private @Nullable String caption;
private @Nullable Boolean isPublic;
private @Nullable Set<String> viewersToAdd;
private @Nullable Set<String> viewersToRemove;
private @Nullable Boolean clearAllViewers;
public @Nullable String getAlt() {
return this.alt;
}
public void setAlt(@Nullable String alt) {
this.alt = alt;
}
public @Nullable String getCaption() {
return this.caption;
}
public void setCaption(@Nullable String caption) {
this.caption = caption;
}
public @Nullable Boolean getPublic() {
return this.isPublic;
}
public void setPublic(@Nullable Boolean aPublic) {
isPublic = aPublic;
}
public @Nullable Set<String> getViewersToAdd() {
return this.viewersToAdd;
}
public void setViewersToAdd(@Nullable Set<String> viewersToAdd) {
this.viewersToAdd = viewersToAdd;
}
public @Nullable Set<String> getViewersToRemove() {
return this.viewersToRemove;
}
public void setViewersToRemove(@Nullable Set<String> viewersToRemove) {
this.viewersToRemove = viewersToRemove;
}
public @Nullable Boolean getClearAllViewers() {
return this.clearAllViewers;
}
public void setClearAllViewers(@Nullable Boolean clearAllViewers) {
this.clearAllViewers = clearAllViewers;
}
}

View File

@ -0,0 +1,48 @@
package app.mealsmadeeasy.api.image.spec;
import app.mealsmadeeasy.api.user.User;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
public class ImageCreateInfoSpec {
private @Nullable String alt;
private @Nullable String caption;
private @Nullable Boolean isPublic;
private Set<User> viewersToAdd = new HashSet<>();
public @Nullable String getAlt() {
return this.alt;
}
public void setAlt(@Nullable String alt) {
this.alt = alt;
}
public @Nullable String getCaption() {
return this.caption;
}
public void setCaption(@Nullable String caption) {
this.caption = caption;
}
public @Nullable Boolean getPublic() {
return this.isPublic;
}
public void setPublic(@Nullable Boolean aPublic) {
isPublic = aPublic;
}
public Set<User> getViewersToAdd() {
return this.viewersToAdd;
}
public void setViewersToAdd(Set<User> viewersToAdd) {
this.viewersToAdd = viewersToAdd;
}
}

View File

@ -0,0 +1,30 @@
package app.mealsmadeeasy.api.image.spec;
import app.mealsmadeeasy.api.user.User;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
public class ImageUpdateInfoSpec extends ImageCreateInfoSpec {
private Set<User> viewersToRemove = new HashSet<>();
private @Nullable Boolean clearAllViewers;
public Set<User> getViewersToRemove() {
return this.viewersToRemove;
}
public void setViewersToRemove(Set<User> viewersToRemove) {
this.viewersToRemove = viewersToRemove;
}
public @Nullable Boolean getClearAllViewers() {
return this.clearAllViewers;
}
public void setClearAllViewers(@Nullable Boolean clearAllViewers) {
this.clearAllViewers = clearAllViewers;
}
}