Get rid of Image interface.
This commit is contained in:
parent
7e95c3a867
commit
bea8af4a0e
@ -115,7 +115,7 @@ public class S3ImageServiceTests {
|
||||
assertThat(image.getMimeType(), is("image/svg+xml"));
|
||||
assertThat(image.getAlt(), is(nullValue()));
|
||||
assertThat(image.getCaption(), is(nullValue()));
|
||||
assertThat(image.isPublic(), is(false));
|
||||
assertThat(image.getIsPublic(), is(false));
|
||||
assertThat(image.getViewers(), is(empty()));
|
||||
}
|
||||
|
||||
@ -206,7 +206,7 @@ public class S3ImageServiceTests {
|
||||
final ImageUpdateInfoSpec spec = new ImageUpdateInfoSpec();
|
||||
spec.setPublic(true);
|
||||
image = this.imageService.update(image, owner, spec);
|
||||
assertThat(image.isPublic(), is(true));
|
||||
assertThat(image.getIsPublic(), is(true));
|
||||
}
|
||||
|
||||
private Image addViewer(Image image, User owner, User viewer) {
|
||||
|
||||
@ -1,22 +1,58 @@
|
||||
package app.mealsmadeeasy.api.image;
|
||||
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Image {
|
||||
Integer getId();
|
||||
OffsetDateTime getCreated();
|
||||
@Nullable OffsetDateTime getModified();
|
||||
String getUserFilename();
|
||||
String getMimeType();
|
||||
@Nullable String getAlt();
|
||||
@Nullable String getCaption();
|
||||
User getOwner();
|
||||
boolean isPublic();
|
||||
@Nullable Integer getHeight();
|
||||
@Nullable Integer getWidth();
|
||||
Set<User> getViewers();
|
||||
@Entity
|
||||
@Table(name = "image")
|
||||
@Data
|
||||
public class Image {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private OffsetDateTime created = OffsetDateTime.now();
|
||||
|
||||
private OffsetDateTime modified;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String userFilename;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String mimeType;
|
||||
|
||||
private String alt;
|
||||
|
||||
private String caption;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String objectName;
|
||||
|
||||
private Integer height;
|
||||
|
||||
private Integer width;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "owner_id", nullable = false)
|
||||
private User owner;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean isPublic = false;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "image_viewer",
|
||||
joinColumns = @JoinColumn(name = "image_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "viewer_id")
|
||||
)
|
||||
private Set<User> viewers = new HashSet<>();
|
||||
|
||||
}
|
||||
|
||||
@ -8,16 +8,16 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface S3ImageRepository extends JpaRepository<S3ImageEntity, Long> {
|
||||
public interface ImageRepository extends JpaRepository<Image, Long> {
|
||||
|
||||
@Query("SELECT image FROM Image image WHERE image.id = ?1")
|
||||
@EntityGraph(attributePaths = { "viewers" })
|
||||
S3ImageEntity getByIdWithViewers(long id);
|
||||
Image getByIdWithViewers(long id);
|
||||
|
||||
List<S3ImageEntity> findAllByOwner(User owner);
|
||||
Optional<S3ImageEntity> findByOwnerAndUserFilename(User owner, String filename);
|
||||
List<Image> findAllByOwner(User owner);
|
||||
Optional<Image> findByOwnerAndUserFilename(User owner, String filename);
|
||||
|
||||
@Query("SELECT image from Image image WHERE image.owner.username = ?1 AND image.userFilename = ?2")
|
||||
Optional<S3ImageEntity> findByOwnerUsernameAndFilename(String username, String filename);
|
||||
Optional<Image> findByOwnerUsernameAndFilename(String username, String filename);
|
||||
|
||||
}
|
||||
@ -9,15 +9,15 @@ import java.util.Objects;
|
||||
@Component("imageSecurity")
|
||||
public class ImageSecurityImpl implements ImageSecurity {
|
||||
|
||||
private final S3ImageRepository imageRepository;
|
||||
private final ImageRepository imageRepository;
|
||||
|
||||
public ImageSecurityImpl(S3ImageRepository imageRepository) {
|
||||
public ImageSecurityImpl(ImageRepository imageRepository) {
|
||||
this.imageRepository = imageRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewableBy(Image image, @Nullable User viewer) {
|
||||
if (image.isPublic()) {
|
||||
if (image.getIsPublic()) {
|
||||
// public image
|
||||
return true;
|
||||
} else if (viewer == null) {
|
||||
@ -28,7 +28,7 @@ public class ImageSecurityImpl implements ImageSecurity {
|
||||
return true;
|
||||
} else {
|
||||
// check if viewer
|
||||
final S3ImageEntity withViewers = this.imageRepository.getByIdWithViewers(image.getId());
|
||||
final Image withViewers = this.imageRepository.getByIdWithViewers(image.getId());
|
||||
for (final User user : withViewers.getViewers()) {
|
||||
if (user.getId() != null && user.getId().equals(viewer.getId())) {
|
||||
return true;
|
||||
|
||||
@ -1,182 +0,0 @@
|
||||
package app.mealsmadeeasy.api.image;
|
||||
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import jakarta.persistence.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity(name = "Image")
|
||||
@Table(name = "image")
|
||||
public class S3ImageEntity implements Image {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private OffsetDateTime created = OffsetDateTime.now();
|
||||
|
||||
private OffsetDateTime modified;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String userFilename;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String mimeType;
|
||||
|
||||
private String alt;
|
||||
|
||||
private String caption;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String objectName;
|
||||
|
||||
private Integer height;
|
||||
|
||||
private Integer width;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "owner_id", nullable = false)
|
||||
private User owner;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean isPublic = false;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "image_viewer",
|
||||
joinColumns = @JoinColumn(name = "image_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "viewer_id")
|
||||
)
|
||||
private Set<User> viewers = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserFilename() {
|
||||
return this.userFilename;
|
||||
}
|
||||
|
||||
public void setUserFilename(String userFilename) {
|
||||
this.userFilename = userFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return this.mimeType;
|
||||
}
|
||||
|
||||
public void setMimeType(String mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getAlt() {
|
||||
return this.alt;
|
||||
}
|
||||
|
||||
public void setAlt(String alt) {
|
||||
this.alt = alt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getCaption() {
|
||||
return this.caption;
|
||||
}
|
||||
|
||||
public void setCaption(String caption) {
|
||||
this.caption = caption;
|
||||
}
|
||||
|
||||
public String getObjectName() {
|
||||
return this.objectName;
|
||||
}
|
||||
|
||||
public void setObjectName(String objectName) {
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Integer getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public void setHeight(Integer height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Integer getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public void setWidth(Integer width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublic() {
|
||||
return this.isPublic;
|
||||
}
|
||||
|
||||
public void setPublic(Boolean aPublic) {
|
||||
isPublic = aPublic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> getViewers() {
|
||||
return Set.copyOf(this.viewers);
|
||||
}
|
||||
|
||||
public Set<User> getViewerEntities() {
|
||||
return this.viewers;
|
||||
}
|
||||
|
||||
public void setViewers(Set<User> viewers) {
|
||||
this.viewers = viewers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "S3ImageEntity(" + this.id + ", " + this.userFilename + ", " + this.objectName + ")";
|
||||
}
|
||||
|
||||
}
|
||||
@ -33,13 +33,13 @@ public class S3ImageService implements ImageService {
|
||||
private static final String IMAGE_WEBP = "image/webp";
|
||||
|
||||
private final S3Manager s3Manager;
|
||||
private final S3ImageRepository imageRepository;
|
||||
private final ImageRepository imageRepository;
|
||||
private final String imageBucketName;
|
||||
private final String baseUrl;
|
||||
|
||||
public S3ImageService(
|
||||
S3Manager s3Manager,
|
||||
S3ImageRepository imageRepository,
|
||||
ImageRepository imageRepository,
|
||||
@Value("${app.mealsmadeeasy.api.images.bucketName}") String imageBucketName,
|
||||
@Value("${app.mealsmadeeasy.api.baseUrl}") String baseUrl
|
||||
) {
|
||||
@ -78,7 +78,7 @@ public class S3ImageService implements ImageService {
|
||||
};
|
||||
}
|
||||
|
||||
private boolean transferFromSpec(S3ImageEntity entity, ImageCreateInfoSpec spec) {
|
||||
private boolean transferFromSpec(Image entity, ImageCreateInfoSpec spec) {
|
||||
boolean didTransfer = false;
|
||||
if (spec.getAlt() != null) {
|
||||
entity.setAlt(spec.getAlt());
|
||||
@ -89,12 +89,12 @@ public class S3ImageService implements ImageService {
|
||||
didTransfer = true;
|
||||
}
|
||||
if (spec.getPublic() != null) {
|
||||
entity.setPublic(spec.getPublic());
|
||||
entity.setIsPublic(spec.getPublic());
|
||||
didTransfer = true;
|
||||
}
|
||||
final @Nullable Set<User> viewersToAdd = spec.getViewersToAdd();
|
||||
if (viewersToAdd != null) {
|
||||
final Set<User> viewers = new HashSet<>(entity.getViewerEntities());
|
||||
final Set<User> viewers = new HashSet<>(entity.getViewers());
|
||||
for (final User viewerToAdd : spec.getViewersToAdd()) {
|
||||
viewers.add((User) viewerToAdd);
|
||||
}
|
||||
@ -152,7 +152,7 @@ public class S3ImageService implements ImageService {
|
||||
toStore.close();
|
||||
inputStream.close();
|
||||
|
||||
final S3ImageEntity draft = new S3ImageEntity();
|
||||
final Image draft = new Image();
|
||||
draft.setOwner((User) owner);
|
||||
draft.setUserFilename(userFilename);
|
||||
draft.setMimeType(mimeType);
|
||||
@ -195,7 +195,7 @@ public class S3ImageService implements ImageService {
|
||||
@Override
|
||||
@PreAuthorize("@imageSecurity.isViewableBy(#image, #viewer)")
|
||||
public InputStream getImageContent(Image image, User viewer) throws IOException {
|
||||
return this.s3Manager.load(this.imageBucketName, ((S3ImageEntity) image).getObjectName());
|
||||
return this.s3Manager.load(this.imageBucketName, ((Image) image).getObjectName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -206,7 +206,7 @@ public class S3ImageService implements ImageService {
|
||||
@Override
|
||||
@PreAuthorize("@imageSecurity.isOwner(#image, #modifier)")
|
||||
public Image update(final Image image, User modifier, ImageUpdateInfoSpec updateSpec) {
|
||||
S3ImageEntity entity = (S3ImageEntity) image;
|
||||
Image entity = (Image) image;
|
||||
boolean didUpdate = this.transferFromSpec(entity, updateSpec);
|
||||
final @Nullable Boolean clearAllViewers = updateSpec.getClearAllViewers();
|
||||
if (clearAllViewers != null && clearAllViewers) {
|
||||
@ -215,7 +215,7 @@ public class S3ImageService implements ImageService {
|
||||
} else {
|
||||
final @Nullable Set<User> viewersToRemove = updateSpec.getViewersToRemove();
|
||||
if (viewersToRemove != null) {
|
||||
final Set<User> currentViewers = new HashSet<>(entity.getViewerEntities());
|
||||
final Set<User> currentViewers = new HashSet<>(entity.getViewers());
|
||||
for (final User toRemove : updateSpec.getViewersToRemove()) {
|
||||
currentViewers.remove((User) toRemove);
|
||||
}
|
||||
@ -232,7 +232,7 @@ public class S3ImageService implements ImageService {
|
||||
@Override
|
||||
@PreAuthorize("@imageSecurity.isOwner(#image, #modifier)")
|
||||
public void deleteImage(Image image, User modifier) throws IOException {
|
||||
final S3ImageEntity imageEntity = (S3ImageEntity) image;
|
||||
final Image imageEntity = (Image) image;
|
||||
this.imageRepository.delete(imageEntity);
|
||||
this.s3Manager.delete("images", imageEntity.getObjectName());
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public class ImageView {
|
||||
view.setAlt(image.getAlt());
|
||||
view.setCaption(image.getCaption());
|
||||
view.setOwner(UserInfoView.from(image.getOwner()));
|
||||
view.setIsPublic(image.isPublic());
|
||||
view.setIsPublic(image.getIsPublic());
|
||||
view.setHeight(image.getHeight());
|
||||
view.setWidth(image.getWidth());
|
||||
if (includeViewers) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package app.mealsmadeeasy.api.recipe;
|
||||
|
||||
import app.mealsmadeeasy.api.image.S3ImageEntity;
|
||||
import app.mealsmadeeasy.api.image.Image;
|
||||
import app.mealsmadeeasy.api.recipe.comment.RecipeComment;
|
||||
import app.mealsmadeeasy.api.recipe.star.RecipeStar;
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
@ -75,7 +75,7 @@ public final class Recipe {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "main_image_id")
|
||||
private S3ImageEntity mainImage;
|
||||
private Image mainImage;
|
||||
|
||||
@OneToOne(mappedBy = "recipe", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private RecipeEmbeddingEntity embedding;
|
||||
|
||||
@ -3,7 +3,6 @@ package app.mealsmadeeasy.api.recipe;
|
||||
import app.mealsmadeeasy.api.image.Image;
|
||||
import app.mealsmadeeasy.api.image.ImageException;
|
||||
import app.mealsmadeeasy.api.image.ImageService;
|
||||
import app.mealsmadeeasy.api.image.S3ImageEntity;
|
||||
import app.mealsmadeeasy.api.image.view.ImageView;
|
||||
import app.mealsmadeeasy.api.markdown.MarkdownService;
|
||||
import app.mealsmadeeasy.api.recipe.spec.RecipeAiSearchSpec;
|
||||
@ -63,7 +62,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
draft.setSlug(spec.getSlug());
|
||||
draft.setTitle(spec.getTitle());
|
||||
draft.setRawText(spec.getRawText());
|
||||
draft.setMainImage((S3ImageEntity) spec.getMainImage());
|
||||
draft.setMainImage((Image) spec.getMainImage());
|
||||
draft.setIsPublic(spec.isPublic());
|
||||
return this.recipeRepository.save(draft);
|
||||
}
|
||||
@ -231,11 +230,11 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
recipe.setCachedRenderedText(null);
|
||||
recipe.setIsPublic(spec.getIsPublic());
|
||||
|
||||
final S3ImageEntity mainImage;
|
||||
final Image mainImage;
|
||||
if (spec.getMainImage() == null) {
|
||||
mainImage = null;
|
||||
} else {
|
||||
mainImage = (S3ImageEntity) this.imageService.getByUsernameAndFilename(
|
||||
mainImage = (Image) this.imageService.getByUsernameAndFilename(
|
||||
spec.getMainImage().getUsername(),
|
||||
spec.getMainImage().getFilename(),
|
||||
modifier
|
||||
|
||||
Loading…
Reference in New Issue
Block a user