Compare commits
4 Commits
315a948971
...
0a619c5d41
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a619c5d41 | ||
|
|
2505a7ee9e | ||
|
|
a24f4192a9 | ||
|
|
e9b106d5de |
@ -66,6 +66,11 @@ dependencies {
|
|||||||
|
|
||||||
compileOnly 'org.jetbrains:annotations:26.0.1'
|
compileOnly 'org.jetbrains:annotations:26.0.1'
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-webp
|
||||||
|
runtimeOnly 'com.twelvemonkeys.imageio:imageio-webp:3.12.0'
|
||||||
|
|
||||||
|
compileOnly 'org.jetbrains:annotations:24.1.0'
|
||||||
|
|
||||||
// Custom testing
|
// Custom testing
|
||||||
testRuntimeOnly 'com.h2database:h2'
|
testRuntimeOnly 'com.h2database:h2'
|
||||||
testImplementation 'org.testcontainers:testcontainers:1.20.4'
|
testImplementation 'org.testcontainers:testcontainers:1.20.4'
|
||||||
|
|||||||
39
compose.dev.yaml
Normal file
39
compose.dev.yaml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
name: meals-made-easy-api-dev
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:latest
|
||||||
|
ports:
|
||||||
|
- '55001:3306'
|
||||||
|
- '55000:33060'
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
MYSQL_DATABASE: meals_made_easy_api
|
||||||
|
MYSQL_USER: meals-made-easy-api-user
|
||||||
|
healthcheck:
|
||||||
|
test: mysqladmin ping -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 10
|
||||||
|
volumes:
|
||||||
|
- mysql-data:/var/lib/mysql
|
||||||
|
minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
ports:
|
||||||
|
- 9000:9000
|
||||||
|
- 9001:9001
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
MINIO_ROOT_USER: minio-root
|
||||||
|
volumes:
|
||||||
|
- minio-data:/data
|
||||||
|
command:
|
||||||
|
- server
|
||||||
|
- /data
|
||||||
|
- --console-address
|
||||||
|
- :9001
|
||||||
|
profiles:
|
||||||
|
- deps
|
||||||
|
volumes:
|
||||||
|
mysql-data:
|
||||||
|
minio-data:
|
||||||
@ -16,7 +16,7 @@ public class MvcConfiguration {
|
|||||||
public void addCorsMappings(CorsRegistry registry) {
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
registry.addMapping("/**")
|
registry.addMapping("/**")
|
||||||
.allowedMethods("GET", "POST", "PUT", "DELETE")
|
.allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||||
.allowedOrigins("http://localhost:5173")
|
.allowedOrigins("http://localhost:5173", "http://localhost:4200")
|
||||||
.allowCredentials(true);
|
.allowCredentials(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,5 +16,7 @@ public interface Image {
|
|||||||
@Nullable String getCaption();
|
@Nullable String getCaption();
|
||||||
User getOwner();
|
User getOwner();
|
||||||
boolean isPublic();
|
boolean isPublic();
|
||||||
|
int getHeight();
|
||||||
|
int getWidth();
|
||||||
Set<User> getViewers();
|
Set<User> getViewers();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,12 @@ public class S3ImageEntity implements Image {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String objectName;
|
private String objectName;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private int width;
|
||||||
|
|
||||||
@ManyToOne(optional = false)
|
@ManyToOne(optional = false)
|
||||||
@JoinColumn(name = "owner_id", nullable = false)
|
@JoinColumn(name = "owner_id", nullable = false)
|
||||||
private UserEntity owner;
|
private UserEntity owner;
|
||||||
@ -116,6 +122,24 @@ public class S3ImageEntity implements Image {
|
|||||||
this.objectName = objectName;
|
this.objectName = objectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(int height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return this.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(int width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getOwner() {
|
public User getOwner() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
|
|||||||
@ -7,11 +7,15 @@ 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.jetbrains.annotations.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
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;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -23,6 +27,7 @@ import java.util.regex.Pattern;
|
|||||||
public class S3ImageService implements ImageService {
|
public class S3ImageService implements ImageService {
|
||||||
|
|
||||||
private static final Pattern extensionPattern = Pattern.compile(".+\\.(.+)$");
|
private static final Pattern extensionPattern = Pattern.compile(".+\\.(.+)$");
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(S3ImageService.class);
|
||||||
|
|
||||||
private final S3Manager s3Manager;
|
private final S3Manager s3Manager;
|
||||||
private final S3ImageRepository imageRepository;
|
private final S3ImageRepository imageRepository;
|
||||||
@ -112,11 +117,23 @@ public class S3ImageService implements ImageService {
|
|||||||
this.imageBucketName, filename, mimeType, inputStream, objectSize
|
this.imageBucketName, filename, mimeType, inputStream, objectSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final int height, width;
|
||||||
|
try (final InputStream imageContent = this.s3Manager.load(this.imageBucketName, objectName)) {
|
||||||
|
final BufferedImage bufferedImage = ImageIO.read(imageContent);
|
||||||
|
if (bufferedImage == null) {
|
||||||
|
logger.error("ImageIO could not read image: {} ({})", userFilename, objectName);
|
||||||
|
}
|
||||||
|
height = bufferedImage.getHeight();
|
||||||
|
width = bufferedImage.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
final S3ImageEntity draft = new S3ImageEntity();
|
final S3ImageEntity draft = new S3ImageEntity();
|
||||||
draft.setOwner((UserEntity) owner);
|
draft.setOwner((UserEntity) owner);
|
||||||
draft.setUserFilename(userFilename);
|
draft.setUserFilename(userFilename);
|
||||||
draft.setMimeType(mimeType);
|
draft.setMimeType(mimeType);
|
||||||
draft.setObjectName(objectName);
|
draft.setObjectName(objectName);
|
||||||
|
draft.setHeight(height);
|
||||||
|
draft.setWidth(width);
|
||||||
this.transferFromSpec(draft, createSpec);
|
this.transferFromSpec(draft, createSpec);
|
||||||
return this.imageRepository.save(draft);
|
return this.imageRepository.save(draft);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ public class ImageView {
|
|||||||
view.setCaption(image.getCaption());
|
view.setCaption(image.getCaption());
|
||||||
view.setOwner(UserInfoView.from(image.getOwner()));
|
view.setOwner(UserInfoView.from(image.getOwner()));
|
||||||
view.setIsPublic(image.isPublic());
|
view.setIsPublic(image.isPublic());
|
||||||
|
view.setHeight(image.getHeight());
|
||||||
|
view.setWidth(image.getWidth());
|
||||||
if (includeViewers) {
|
if (includeViewers) {
|
||||||
view.setViewers(image.getViewers().stream()
|
view.setViewers(image.getViewers().stream()
|
||||||
.map(UserInfoView::from)
|
.map(UserInfoView::from)
|
||||||
@ -39,6 +41,8 @@ public class ImageView {
|
|||||||
private @Nullable String caption;
|
private @Nullable String caption;
|
||||||
private UserInfoView owner;
|
private UserInfoView owner;
|
||||||
private boolean isPublic;
|
private boolean isPublic;
|
||||||
|
private int height;
|
||||||
|
private int width;
|
||||||
private @Nullable Set<UserInfoView> viewers;
|
private @Nullable Set<UserInfoView> viewers;
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
@ -113,6 +117,22 @@ public class ImageView {
|
|||||||
this.isPublic = isPublic;
|
this.isPublic = isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight(int height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return this.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth(int width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
public @Nullable Set<UserInfoView> getViewers() {
|
public @Nullable Set<UserInfoView> getViewers() {
|
||||||
return this.viewers;
|
return this.viewers;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user