S3ImageServiceTests all passing.

This commit is contained in:
Jesse Brault 2024-07-26 10:38:11 -05:00
parent a5c0add82b
commit 6e29ec7d58
6 changed files with 102 additions and 20 deletions

View File

@ -22,13 +22,14 @@ import java.util.List;
import java.util.Set; 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.ContainsUsersMatcher.containsUsers;
import static app.mealsmadeeasy.api.user.IsUserMatcher.isUser; import static app.mealsmadeeasy.api.user.IsUserMatcher.isUser;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue; 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; import static org.junit.Assert.assertThrows;
@Testcontainers @Testcontainers
@SpringBootTest @SpringBootTest
@ -165,43 +166,89 @@ public class S3ImageServiceTests {
@Test @Test
@DirtiesContext @DirtiesContext
public void updateAlt() throws Exception { public void updateAlt() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
Image image = this.createHal9000(owner);
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setAlt("HAL 9000");
image = this.imageService.update(image, owner, spec);
assertThat(image.getAlt(), is("HAL 9000"));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void updateCaption() throws Exception { public void updateCaption() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
Image image = this.createHal9000(owner);
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setCaption("HAL 9000 from 2001: A Space Odyssey");
image = this.imageService.update(image, owner, spec);
assertThat(image.getCaption(), is("HAL 9000 from 2001: A Space Odyssey"));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void updateIsPublic() throws Exception { public void updateIsPublic() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
Image image = this.createHal9000(owner);
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
spec.setPublic(true);
image = this.imageService.update(image, owner, spec);
assertThat(image.isPublic(), is(true));
}
private Image addViewer(Image image, User owner, User viewer) {
final ImageUpdateInfoSpec spec0 = new ImageUpdateInfoSpec();
spec0.setViewersToAdd(Set.of(viewer));
return this.imageService.update(image, owner, spec0);
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void addViewers() throws Exception { public void addViewers() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
final User viewer = this.createTestUser("imageViewer");
Image image = this.createHal9000(owner);
image = this.addViewer(image, owner, viewer);
assertThat(image.getViewers(), containsUsers(viewer));
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void removeViewers() throws Exception { public void removeViewers() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
final User viewer = this.createTestUser("imageViewer");
Image image = this.createHal9000(owner);
image = this.addViewer(image, owner, viewer);
assertThat(image.getViewers(), containsUsers(viewer));
final ImageUpdateInfoSpec spec1 = new ImageUpdateInfoSpec();
spec1.setViewersToRemove(Set.of(viewer));
image = this.imageService.update(image, owner, spec1);
assertThat(image.getViewers(), empty());
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void clearAllViewers() throws Exception { public void clearAllViewers() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
final User viewer = this.createTestUser("imageViewer");
Image image = this.createHal9000(owner);
image = this.addViewer(image, owner, viewer);
assertThat(image.getViewers(), containsUsers(viewer));
final ImageUpdateInfoSpec spec1 = new ImageUpdateInfoSpec();
spec1.setClearAllViewers(true);
image = this.imageService.update(image, owner, spec1);
assertThat(image.getViewers(), empty());
} }
@Test @Test
@DirtiesContext @DirtiesContext
public void deleteImage() throws Exception { public void deleteImage() throws Exception {
fail("TODO"); final User owner = this.createTestUser("imageOwner");
final Image image = this.createHal9000(owner);
this.imageService.deleteImage(image, owner);
assertThrows(ImageException.class, () -> this.imageService.getById(image.getId(), owner));
} }
} }

View File

@ -1,7 +1,6 @@
package app.mealsmadeeasy.api.image; package app.mealsmadeeasy.api.image;
import app.mealsmadeeasy.api.user.User; import app.mealsmadeeasy.api.user.User;
import app.mealsmadeeasy.api.user.UserEntity;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -17,5 +16,5 @@ public interface Image {
@Nullable String getCaption(); @Nullable String getCaption();
User getOwner(); User getOwner();
boolean isPublic(); boolean isPublic();
Set<UserEntity> getViewers(); Set<User> getViewers();
} }

View File

@ -14,7 +14,9 @@ public interface ImageService {
Image create(User owner, String userFilename, InputStream inputStream, long objectSize, ImageCreateInfoSpec infoSpec) Image create(User owner, String userFilename, InputStream inputStream, long objectSize, ImageCreateInfoSpec infoSpec)
throws IOException, ImageException; throws IOException, ImageException;
Image getById(long id, @Nullable User viewer) throws 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);

View File

@ -135,7 +135,11 @@ public class S3ImageEntity implements Image {
} }
@Override @Override
public Set<UserEntity> getViewers() { public Set<User> getViewers() {
return Set.copyOf(this.viewers);
}
public Set<UserEntity> getViewerEntities() {
return this.viewers; return this.viewers;
} }

View File

@ -5,6 +5,7 @@ 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;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -12,9 +13,7 @@ import org.springframework.stereotype.Service;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -75,9 +74,11 @@ public class S3ImageService implements ImageService {
if (spec.getPublic() != null) { if (spec.getPublic() != null) {
entity.setPublic(spec.getPublic()); entity.setPublic(spec.getPublic());
} }
final Set<UserEntity> viewers = new HashSet<>(entity.getViewerEntities());
for (final User viewerToAdd : spec.getViewersToAdd()) { for (final User viewerToAdd : spec.getViewersToAdd()) {
entity.getViewers().add((UserEntity) viewerToAdd); viewers.add((UserEntity) viewerToAdd);
} }
entity.setViewers(viewers);
} }
@Override @Override
@ -105,6 +106,14 @@ public class S3ImageService implements ImageService {
return this.imageRepository.save(draft); return this.imageRepository.save(draft);
} }
@Override
@PostAuthorize("@imageSecurity.isViewableBy(returnObject, #viewer)")
public Image getById(long id, @Nullable User viewer) throws ImageException {
return this.imageRepository.findById(id).orElseThrow(() -> new ImageException(
ImageException.Type.INVALID_ID, "No Image with id: " + id
));
}
@Override @Override
@PostAuthorize("@imageSecurity.isViewableBy(returnObject, #viewer)") @PostAuthorize("@imageSecurity.isViewableBy(returnObject, #viewer)")
public Image getByOwnerAndFilename(User owner, String filename, User viewer) throws ImageException { public Image getByOwnerAndFilename(User owner, String filename, User viewer) throws ImageException {
@ -131,11 +140,15 @@ public class S3ImageService implements ImageService {
public Image update(final Image image, User modifier, ImageUpdateInfoSpec updateSpec) { public Image update(final Image image, User modifier, ImageUpdateInfoSpec updateSpec) {
S3ImageEntity entity = (S3ImageEntity) image; S3ImageEntity entity = (S3ImageEntity) image;
this.transferFromSpec(entity, updateSpec); this.transferFromSpec(entity, updateSpec);
for (final User toRemove : updateSpec.getViewersToRemove()) { final @Nullable Boolean clearAllViewers = updateSpec.getClearAllViewers();
entity.getViewers().remove((UserEntity) toRemove); if (clearAllViewers != null && clearAllViewers) {
} entity.setViewers(Set.of());
if (updateSpec.getClearAllViewers() != null) { } else {
entity.getViewers().clear(); final Set<UserEntity> viewers = new HashSet<>(entity.getViewerEntities());
for (final User toRemove : updateSpec.getViewersToRemove()) {
viewers.remove((UserEntity) toRemove);
}
entity.setViewers(viewers);
} }
return this.imageRepository.save(entity); return this.imageRepository.save(entity);
} }

View File

@ -0,0 +1,17 @@
package app.mealsmadeeasy.api.user;
import app.mealsmadeeasy.api.matchers.ContainsItemsMatcher;
import java.util.List;
public class ContainsUsersMatcher extends ContainsItemsMatcher<User, Long> {
public static ContainsUsersMatcher containsUsers(User... allExpected) {
return new ContainsUsersMatcher(allExpected);
}
private ContainsUsersMatcher(User... allExpected) {
super(List.of(allExpected), o -> o instanceof User, User::getId);
}
}