Change to flyway migrations, many SQL/entity updates.
This commit is contained in:
parent
52136a34bd
commit
1fefeaa1da
@ -49,12 +49,17 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-jackson'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-flyway'
|
||||
runtimeOnly 'org.postgresql:postgresql'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-jackson-test'
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
|
||||
// flyway
|
||||
implementation 'org.flywaydb:flyway-core'
|
||||
implementation 'org.flywaydb:flyway-database-postgresql'
|
||||
|
||||
// Custom
|
||||
implementation 'io.jsonwebtoken:jjwt-api:0.13.0'
|
||||
implementation 'io.jsonwebtoken:jjwt-jackson:0.13.0'
|
||||
|
||||
@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
@ -36,7 +36,7 @@ public class RecipeStarRepositoryTests {
|
||||
|
||||
private RecipeEntity getTestRecipe(UserEntity owner) {
|
||||
final RecipeEntity recipeDraft = new RecipeEntity();
|
||||
recipeDraft.setCreated(LocalDateTime.now());
|
||||
recipeDraft.setCreated(OffsetDateTime.now());
|
||||
recipeDraft.setSlug("test-recipe");
|
||||
recipeDraft.setOwner(owner);
|
||||
recipeDraft.setTitle("Test Recipe");
|
||||
@ -53,7 +53,7 @@ public class RecipeStarRepositoryTests {
|
||||
final RecipeStarEntity starDraft = new RecipeStarEntity();
|
||||
final RecipeStarId starId = new RecipeStarId();
|
||||
starId.setRecipeId(recipe.getId());
|
||||
starId.setOwnerUsername(owner.getUsername());
|
||||
starId.getOwnerId(owner.getId());
|
||||
starDraft.setId(starId);
|
||||
this.recipeStarRepository.save(starDraft);
|
||||
|
||||
@ -61,7 +61,7 @@ public class RecipeStarRepositoryTests {
|
||||
this.recipeStarRepository.isStarer(
|
||||
recipe.getOwner().getUsername(),
|
||||
recipe.getSlug(),
|
||||
owner.getUsername()
|
||||
owner.getId()
|
||||
),
|
||||
is(true)
|
||||
);
|
||||
@ -76,7 +76,7 @@ public class RecipeStarRepositoryTests {
|
||||
this.recipeStarRepository.isStarer(
|
||||
recipe.getOwner().getUsername(),
|
||||
recipe.getSlug(),
|
||||
owner.getUsername()
|
||||
owner.getId()
|
||||
),
|
||||
is(false)
|
||||
);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package app.mealsmadeeasy.api.auth;
|
||||
|
||||
import app.mealsmadeeasy.api.security.AuthToken;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -8,6 +7,8 @@ import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public final class AuthController {
|
||||
@ -31,9 +32,9 @@ public final class AuthController {
|
||||
}
|
||||
|
||||
private ResponseEntity<LoginView> getLoginViewResponseEntity(LoginDetails loginDetails) {
|
||||
final AuthToken refreshToken = loginDetails.getRefreshToken();
|
||||
final RefreshToken refreshToken = loginDetails.getRefreshToken();
|
||||
final ResponseCookie refreshCookie = getRefreshTokenCookie(
|
||||
refreshToken.getToken(),
|
||||
refreshToken.getToken().toString(),
|
||||
refreshToken.getLifetime()
|
||||
);
|
||||
final var loginView = new LoginView(
|
||||
@ -60,7 +61,7 @@ public final class AuthController {
|
||||
|
||||
@PostMapping("/refresh")
|
||||
public ResponseEntity<LoginView> refresh(
|
||||
@CookieValue(value = "refresh-token", required = false) @Nullable String oldRefreshToken
|
||||
@CookieValue(value = "refresh-token", required = false) @Nullable UUID oldRefreshToken
|
||||
) throws LoginException {
|
||||
final LoginDetails loginDetails = this.authService.refresh(oldRefreshToken);
|
||||
return this.getLoginViewResponseEntity(loginDetails);
|
||||
@ -68,7 +69,7 @@ public final class AuthController {
|
||||
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<?> logout(
|
||||
@CookieValue(value = "refresh-token", required = false) @Nullable String refreshToken
|
||||
@CookieValue(value = "refresh-token", required = false) @Nullable UUID refreshToken
|
||||
) {
|
||||
if (refreshToken != null) {
|
||||
this.authService.logout(refreshToken);
|
||||
|
||||
@ -2,8 +2,10 @@ package app.mealsmadeeasy.api.auth;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AuthService {
|
||||
LoginDetails login(String username, String password) throws LoginException;
|
||||
void logout(String refreshToken);
|
||||
LoginDetails refresh(@Nullable String refreshToken) throws LoginException;
|
||||
void logout(UUID refreshToken);
|
||||
LoginDetails refresh(@Nullable UUID refreshToken) throws LoginException;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -38,9 +38,9 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
private RefreshToken createRefreshToken(UserEntity principal) {
|
||||
final RefreshTokenEntity refreshTokenDraft = new RefreshTokenEntity();
|
||||
refreshTokenDraft.setToken(UUID.randomUUID().toString());
|
||||
refreshTokenDraft.setIssued(LocalDateTime.now());
|
||||
refreshTokenDraft.setExpiration(LocalDateTime.now().plusSeconds(this.refreshTokenLifetime));
|
||||
refreshTokenDraft.setToken(UUID.randomUUID());
|
||||
refreshTokenDraft.setIssued(OffsetDateTime.now());
|
||||
refreshTokenDraft.setExpiration(OffsetDateTime.now().plusSeconds(this.refreshTokenLifetime));
|
||||
refreshTokenDraft.setOwner(principal);
|
||||
return this.refreshTokenRepository.save(refreshTokenDraft);
|
||||
}
|
||||
@ -64,13 +64,13 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void logout(String refreshToken) {
|
||||
public void logout(UUID refreshToken) {
|
||||
this.refreshTokenRepository.findByToken(refreshToken).ifPresent(this.refreshTokenRepository::delete);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public LoginDetails refresh(@Nullable String refreshToken) throws LoginException {
|
||||
public LoginDetails refresh(@Nullable UUID refreshToken) throws LoginException {
|
||||
if (refreshToken == null) {
|
||||
throw new LoginException(LoginExceptionReason.NO_REFRESH_TOKEN, "No refresh token provided.");
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class AuthServiceImpl implements AuthService {
|
||||
if (old.isRevoked() || old.isDeleted()) {
|
||||
throw new LoginException(LoginExceptionReason.INVALID_REFRESH_TOKEN, "Invalid refresh token.");
|
||||
}
|
||||
if (old.getExpires().isBefore(LocalDateTime.now())) {
|
||||
if (old.getExpires().isBefore(OffsetDateTime.now())) {
|
||||
throw new LoginException(LoginExceptionReason.EXPIRED_REFRESH_TOKEN, "Refresh token is expired.");
|
||||
}
|
||||
|
||||
|
||||
@ -6,9 +6,9 @@ public final class LoginDetails {
|
||||
|
||||
private final String username;
|
||||
private final AuthToken accessToken;
|
||||
private final AuthToken refreshToken;
|
||||
private final RefreshToken refreshToken;
|
||||
|
||||
public LoginDetails(String username, AuthToken accessToken, AuthToken refreshToken) {
|
||||
public LoginDetails(String username, AuthToken accessToken, RefreshToken refreshToken) {
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
@ -22,7 +22,7 @@ public final class LoginDetails {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
public AuthToken getRefreshToken() {
|
||||
public RefreshToken getRefreshToken() {
|
||||
return this.refreshToken;
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package app.mealsmadeeasy.api.auth;
|
||||
|
||||
import app.mealsmadeeasy.api.security.AuthToken;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public interface RefreshToken extends AuthToken {
|
||||
LocalDateTime getIssued();
|
||||
public interface RefreshToken {
|
||||
UUID getToken();
|
||||
long getLifetime();
|
||||
OffsetDateTime getExpires();
|
||||
OffsetDateTime getIssued();
|
||||
boolean isRevoked();
|
||||
boolean isDeleted();
|
||||
}
|
||||
|
||||
@ -3,68 +3,58 @@ package app.mealsmadeeasy.api.auth;
|
||||
import app.mealsmadeeasy.api.user.UserEntity;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity(name = "RefreshToken")
|
||||
@Table(name = "refresh_token")
|
||||
public class RefreshTokenEntity implements RefreshToken {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String token;
|
||||
@Column(nullable = false)
|
||||
private UUID token;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime issued;
|
||||
private OffsetDateTime issued;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime expiration;
|
||||
private OffsetDateTime expiration;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean revoked = false;
|
||||
|
||||
@JoinColumn(nullable = false)
|
||||
@ManyToOne
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "owner_id", nullable = false)
|
||||
private UserEntity owner;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean deleted = false;
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
@Column(nullable = false)
|
||||
private Boolean revoked = false;
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
public UUID getToken() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
public void setToken(UUID token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getIssued() {
|
||||
public OffsetDateTime getIssued() {
|
||||
return this.issued;
|
||||
}
|
||||
|
||||
public void setIssued(LocalDateTime issued) {
|
||||
public void setIssued(OffsetDateTime issued) {
|
||||
this.issued = issued;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getExpires() {
|
||||
public OffsetDateTime getExpires() {
|
||||
return this.expiration;
|
||||
}
|
||||
|
||||
public void setExpiration(LocalDateTime expiration) {
|
||||
public void setExpiration(OffsetDateTime expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
|
||||
@ -6,10 +6,11 @@ import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RefreshTokenRepository extends JpaRepository<RefreshTokenEntity, Long> {
|
||||
|
||||
Optional<RefreshTokenEntity> findByToken(String token);
|
||||
Optional<RefreshTokenEntity> findByToken(UUID token);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
|
||||
@ -3,13 +3,13 @@ package app.mealsmadeeasy.api.image;
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Image {
|
||||
Long getId();
|
||||
LocalDateTime getCreated();
|
||||
@Nullable LocalDateTime getModified();
|
||||
Integer getId();
|
||||
OffsetDateTime getCreated();
|
||||
@Nullable OffsetDateTime getModified();
|
||||
String getUserFilename();
|
||||
String getMimeType();
|
||||
@Nullable String getAlt();
|
||||
|
||||
@ -5,22 +5,23 @@ import app.mealsmadeeasy.api.user.UserEntity;
|
||||
import jakarta.persistence.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
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.AUTO)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Long id;
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime created = LocalDateTime.now();
|
||||
private OffsetDateTime created = OffsetDateTime.now();
|
||||
|
||||
private LocalDateTime modified;
|
||||
private OffsetDateTime modified;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String userFilename;
|
||||
@ -47,32 +48,37 @@ public class S3ImageEntity implements Image {
|
||||
private Boolean isPublic = false;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "image_viewer",
|
||||
joinColumns = @JoinColumn(name = "image_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "viewer_id")
|
||||
)
|
||||
private Set<UserEntity> viewers = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable LocalDateTime getModified() {
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(LocalDateTime modified) {
|
||||
public void setModified(OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -225,7 +225,7 @@ public class S3ImageService implements ImageService {
|
||||
}
|
||||
}
|
||||
if (didUpdate) {
|
||||
entity.setModified(LocalDateTime.now());
|
||||
entity.setModified(OffsetDateTime.now());
|
||||
}
|
||||
return this.imageRepository.save(entity);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import app.mealsmadeeasy.api.image.Image;
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -33,8 +33,8 @@ public class ImageView {
|
||||
}
|
||||
|
||||
private String url;
|
||||
private LocalDateTime created;
|
||||
private @Nullable LocalDateTime modified;
|
||||
private OffsetDateTime created;
|
||||
private @Nullable OffsetDateTime modified;
|
||||
private String filename;
|
||||
private String mimeType;
|
||||
private @Nullable String alt;
|
||||
@ -53,19 +53,19 @@ public class ImageView {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public @Nullable LocalDateTime getModified() {
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable LocalDateTime modified) {
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@ import app.mealsmadeeasy.api.recipe.star.RecipeStar;
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
public interface Recipe {
|
||||
Long getId();
|
||||
LocalDateTime getCreated();
|
||||
@Nullable LocalDateTime getModified();
|
||||
Integer getId();
|
||||
OffsetDateTime getCreated();
|
||||
@Nullable OffsetDateTime getModified();
|
||||
String getSlug();
|
||||
String getTitle();
|
||||
@Nullable Integer getPreparationTime();
|
||||
|
||||
@ -10,7 +10,7 @@ import app.mealsmadeeasy.api.user.UserEntity;
|
||||
import jakarta.persistence.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@ -18,14 +18,14 @@ import java.util.Set;
|
||||
public final class RecipeEntity implements Recipe {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false, updatable = false)
|
||||
private Long id;
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime created;
|
||||
private OffsetDateTime created;
|
||||
|
||||
private LocalDateTime modified;
|
||||
private OffsetDateTime modified;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String slug;
|
||||
@ -57,7 +57,7 @@ public final class RecipeEntity implements Recipe {
|
||||
private UserEntity owner;
|
||||
|
||||
@OneToMany
|
||||
@JoinColumn(name = "recipeId")
|
||||
@JoinColumn(name = "recipe_id")
|
||||
private Set<RecipeStarEntity> stars = new HashSet<>();
|
||||
|
||||
@OneToMany(mappedBy = "recipe")
|
||||
@ -67,35 +67,41 @@ public final class RecipeEntity implements Recipe {
|
||||
private Boolean isPublic = false;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "recipe_viewer",
|
||||
joinColumns = @JoinColumn(name = "recipe_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "viewer_id")
|
||||
)
|
||||
private Set<UserEntity> viewers = new HashSet<>();
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "main_image_id")
|
||||
private S3ImageEntity mainImage;
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable LocalDateTime getModified() {
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable LocalDateTime modified) {
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -53,7 +53,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
throw new AccessDeniedException("Must be logged in.");
|
||||
}
|
||||
final RecipeEntity draft = new RecipeEntity();
|
||||
draft.setCreated(LocalDateTime.now());
|
||||
draft.setCreated(OffsetDateTime.now());
|
||||
draft.setOwner((UserEntity) owner);
|
||||
draft.setSlug(spec.getSlug());
|
||||
draft.setTitle(spec.getTitle());
|
||||
@ -222,7 +222,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
}
|
||||
recipe.setMainImage(mainImage);
|
||||
|
||||
recipe.setModified(LocalDateTime.now());
|
||||
recipe.setModified(OffsetDateTime.now());
|
||||
return this.recipeRepository.save(recipe);
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ public class RecipeServiceImpl implements RecipeService {
|
||||
if (viewer == null) {
|
||||
return null;
|
||||
}
|
||||
return this.recipeStarRepository.isStarer(username, slug, viewer.getUsername());
|
||||
return this.recipeStarRepository.isStarer(username, slug, viewer.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -4,12 +4,12 @@ import app.mealsmadeeasy.api.recipe.Recipe;
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public interface RecipeComment {
|
||||
Long getId();
|
||||
LocalDateTime getCreated();
|
||||
@Nullable LocalDateTime getModified();
|
||||
Integer getId();
|
||||
OffsetDateTime getCreated();
|
||||
@Nullable OffsetDateTime getModified();
|
||||
String getRawText();
|
||||
User getOwner();
|
||||
Recipe getRecipe();
|
||||
|
||||
@ -4,20 +4,21 @@ import app.mealsmadeeasy.api.recipe.RecipeEntity;
|
||||
import app.mealsmadeeasy.api.user.UserEntity;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Entity(name = "RecipeComment")
|
||||
@Table(name = "recipe_comment")
|
||||
public final class RecipeCommentEntity implements RecipeComment {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false)
|
||||
private Long id;
|
||||
private Integer id;
|
||||
|
||||
@Column(nullable = false, updatable = false)
|
||||
private LocalDateTime created = LocalDateTime.now();
|
||||
private OffsetDateTime created = OffsetDateTime.now();
|
||||
|
||||
private LocalDateTime modified;
|
||||
private OffsetDateTime modified;
|
||||
|
||||
@Lob
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
@ -35,29 +36,29 @@ public final class RecipeCommentEntity implements RecipeComment {
|
||||
@JoinColumn(name = "recipe_id", nullable = false, updatable = false)
|
||||
private RecipeEntity recipe;
|
||||
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getModified() {
|
||||
public OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(LocalDateTime modified) {
|
||||
public void setModified(OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import org.springframework.security.access.prepost.PostAuthorize;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@ -43,7 +43,7 @@ public class RecipeCommentServiceImpl implements RecipeCommentService {
|
||||
) throws RecipeException {
|
||||
requireNonNull(commenter);
|
||||
final RecipeCommentEntity draft = new RecipeCommentEntity();
|
||||
draft.setCreated(LocalDateTime.now());
|
||||
draft.setCreated(OffsetDateTime.now());
|
||||
draft.setRawText(body.getText());
|
||||
draft.setCachedRenderedText(this.markdownService.renderAndCleanMarkdown(body.getText()));
|
||||
draft.setOwner((UserEntity) commenter);
|
||||
|
||||
@ -3,7 +3,7 @@ package app.mealsmadeeasy.api.recipe.comment;
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public class RecipeCommentView {
|
||||
|
||||
@ -21,35 +21,35 @@ public class RecipeCommentView {
|
||||
return view;
|
||||
}
|
||||
|
||||
private Long id;
|
||||
private LocalDateTime created;
|
||||
private @Nullable LocalDateTime modified;
|
||||
private Integer id;
|
||||
private OffsetDateTime created;
|
||||
private @Nullable OffsetDateTime modified;
|
||||
private String text;
|
||||
private @Nullable String rawText;
|
||||
private UserInfoView owner;
|
||||
private Long recipeId;
|
||||
private Integer recipeId;
|
||||
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public @Nullable LocalDateTime getModified() {
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable LocalDateTime modified) {
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
@ -77,11 +77,11 @@ public class RecipeCommentView {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Long getRecipeId() {
|
||||
public Integer getRecipeId() {
|
||||
return this.recipeId;
|
||||
}
|
||||
|
||||
public void setRecipeId(Long recipeId) {
|
||||
public void setRecipeId(Integer recipeId) {
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package app.mealsmadeeasy.api.recipe.star;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public interface RecipeStar {
|
||||
LocalDateTime getDate();
|
||||
OffsetDateTime getTimestamp();
|
||||
}
|
||||
|
||||
@ -3,17 +3,19 @@ package app.mealsmadeeasy.api.recipe.star;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
@Entity(name = "RecipeStar")
|
||||
@Table(name = "recipe_star")
|
||||
public final class RecipeStarEntity implements RecipeStar {
|
||||
|
||||
@EmbeddedId
|
||||
private RecipeStarId id;
|
||||
|
||||
@Column(nullable = false, updatable = false)
|
||||
private LocalDateTime date = LocalDateTime.now();
|
||||
private OffsetDateTime timestamp = OffsetDateTime.now();
|
||||
|
||||
public RecipeStarId getId() {
|
||||
return this.id;
|
||||
@ -23,13 +25,12 @@ public final class RecipeStarEntity implements RecipeStar {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime getDate() {
|
||||
return this.date;
|
||||
public OffsetDateTime getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
|
||||
public void setDate(LocalDateTime date) {
|
||||
this.date = date;
|
||||
public void setTimestamp(OffsetDateTime date) {
|
||||
this.timestamp = date;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -8,25 +8,25 @@ import java.util.Objects;
|
||||
@Embeddable
|
||||
public class RecipeStarId {
|
||||
|
||||
@Column(nullable = false)
|
||||
private String ownerUsername;
|
||||
@Column(name = "owner_id", nullable = false)
|
||||
private Integer ownerId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long recipeId;
|
||||
@Column(name = "recipe_id", nullable = false)
|
||||
private Integer recipeId;
|
||||
|
||||
public String getOwnerUsername() {
|
||||
return this.ownerUsername;
|
||||
public Integer getOwnerId() {
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
public void setOwnerUsername(String ownerUsername) {
|
||||
this.ownerUsername = ownerUsername;
|
||||
public void getOwnerId(Integer ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public Long getRecipeId() {
|
||||
public Integer getRecipeId() {
|
||||
return this.recipeId;
|
||||
}
|
||||
|
||||
public void setRecipeId(Long recipeId) {
|
||||
public void setRecipeId(Integer recipeId) {
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
@ -34,19 +34,19 @@ public class RecipeStarId {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o instanceof RecipeStarId other) {
|
||||
return this.recipeId.equals(other.recipeId) && this.ownerUsername.equals(other.ownerUsername);
|
||||
return this.recipeId.equals(other.recipeId) && this.ownerId.equals(other.ownerId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.recipeId, this.ownerUsername);
|
||||
return Objects.hash(this.recipeId, this.ownerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RecipeStarId(" + this.recipeId + ", " + this.ownerUsername + ")";
|
||||
return "RecipeStarId(" + this.recipeId + ", " + this.ownerId + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,15 +9,15 @@ import java.util.Optional;
|
||||
|
||||
public interface RecipeStarRepository extends JpaRepository<RecipeStarEntity, Long> {
|
||||
|
||||
@Query("SELECT star FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
||||
Optional<RecipeStarEntity> findByRecipeIdAndOwnerUsername(Long recipeId, String username);
|
||||
@Query("SELECT star FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerId = ?2")
|
||||
Optional<RecipeStarEntity> findByRecipeIdAndOwnerId(Integer recipeId, Integer ownerId);
|
||||
|
||||
@Query("SELECT count(rs) > 0 FROM RecipeStar rs, Recipe r WHERE r.owner.username = ?1 AND r.slug = ?2 AND r.id = rs.id.recipeId AND rs.id.ownerUsername = ?3")
|
||||
boolean isStarer(String ownerUsername, String slug, String viewerUsername);
|
||||
@Query("SELECT count(rs) > 0 FROM RecipeStar rs, Recipe r WHERE r.owner.username = ?1 AND r.slug = ?2 AND r.id = rs.id.recipeId AND rs.id.ownerId = ?3")
|
||||
boolean isStarer(String ownerUsername, String slug, Integer viewerId);
|
||||
|
||||
@Modifying
|
||||
@Transactional
|
||||
@Query("DELETE FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerUsername = ?2")
|
||||
void deleteByRecipeIdAndOwnerUsername(Long recipeId, String username);
|
||||
@Query("DELETE FROM RecipeStar star WHERE star.id.recipeId = ?1 AND star.id.ownerId = ?2")
|
||||
void deleteByRecipeIdAndOwnerId(Integer recipeId, Integer ownerId);
|
||||
|
||||
}
|
||||
|
||||
@ -6,11 +6,11 @@ import app.mealsmadeeasy.api.user.User;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface RecipeStarService {
|
||||
RecipeStar create(long recipeId, String ownerUsername);
|
||||
RecipeStar create(Integer recipeId, Integer ownerId);
|
||||
RecipeStar create(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException;
|
||||
|
||||
Optional<RecipeStar> find(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException;
|
||||
|
||||
void delete(long recipeId, String ownerUsername);
|
||||
void delete(Integer recipeId, Integer ownerId);
|
||||
void delete(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import app.mealsmadeeasy.api.recipe.RecipeService;
|
||||
import app.mealsmadeeasy.api.user.User;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@ -21,45 +21,45 @@ public class RecipeStarServiceImpl implements RecipeStarService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeStar create(long recipeId, String ownerUsername) {
|
||||
public RecipeStar create(Integer recipeId, Integer ownerId) {
|
||||
final RecipeStarEntity draft = new RecipeStarEntity();
|
||||
final RecipeStarId id = new RecipeStarId();
|
||||
id.setRecipeId(recipeId);
|
||||
id.setOwnerUsername(ownerUsername);
|
||||
id.getOwnerId(ownerId);
|
||||
draft.setId(id);
|
||||
draft.setDate(LocalDateTime.now());
|
||||
draft.setTimestamp(OffsetDateTime.now());
|
||||
return this.recipeStarRepository.save(draft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecipeStar create(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException {
|
||||
final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
|
||||
final Optional<RecipeStarEntity> existing = this.recipeStarRepository.findByRecipeIdAndOwnerUsername(
|
||||
final Optional<RecipeStarEntity> existing = this.recipeStarRepository.findByRecipeIdAndOwnerId(
|
||||
recipe.getId(),
|
||||
starer.getUsername()
|
||||
starer.getId()
|
||||
);
|
||||
if (existing.isPresent()) {
|
||||
return existing.get();
|
||||
}
|
||||
return this.create(recipe.getId(), starer.getUsername());
|
||||
return this.create(recipe.getId(), starer.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RecipeStar> find(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException {
|
||||
final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
|
||||
return this.recipeStarRepository.findByRecipeIdAndOwnerUsername(recipe.getId(), starer.getUsername())
|
||||
return this.recipeStarRepository.findByRecipeIdAndOwnerId(recipe.getId(), starer.getId())
|
||||
.map(RecipeStar.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(long recipeId, String ownerUsername) {
|
||||
this.recipeStarRepository.deleteByRecipeIdAndOwnerUsername(recipeId, ownerUsername);
|
||||
public void delete(Integer recipeId, Integer ownerId) {
|
||||
this.recipeStarRepository.deleteByRecipeIdAndOwnerId(recipeId, ownerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String recipeOwnerUsername, String recipeSlug, User starer) throws RecipeException {
|
||||
final Recipe recipe = this.recipeService.getByUsernameAndSlug(recipeOwnerUsername, recipeSlug, starer);
|
||||
this.delete(recipe.getId(), starer.getUsername());
|
||||
this.delete(recipe.getId(), starer.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public class FullRecipeView {
|
||||
|
||||
@ -41,8 +41,8 @@ public class FullRecipeView {
|
||||
}
|
||||
|
||||
private long id;
|
||||
private LocalDateTime created;
|
||||
private @Nullable LocalDateTime modified;
|
||||
private OffsetDateTime created;
|
||||
private @Nullable OffsetDateTime modified;
|
||||
private String slug;
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
@ -64,19 +64,19 @@ public class FullRecipeView {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public @Nullable LocalDateTime getModified() {
|
||||
public @Nullable OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(@Nullable LocalDateTime modified) {
|
||||
public void setModified(@Nullable OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import app.mealsmadeeasy.api.recipe.Recipe;
|
||||
import app.mealsmadeeasy.api.user.view.UserInfoView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
public final class RecipeInfoView {
|
||||
|
||||
@ -27,8 +27,8 @@ public final class RecipeInfoView {
|
||||
}
|
||||
|
||||
private long id;
|
||||
private LocalDateTime created;
|
||||
private LocalDateTime modified;
|
||||
private OffsetDateTime created;
|
||||
private OffsetDateTime modified;
|
||||
private String slug;
|
||||
private String title;
|
||||
private @Nullable Integer preparationTime;
|
||||
@ -47,19 +47,19 @@ public final class RecipeInfoView {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreated() {
|
||||
public OffsetDateTime getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public void setCreated(LocalDateTime created) {
|
||||
public void setCreated(OffsetDateTime created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public LocalDateTime getModified() {
|
||||
public OffsetDateTime getModified() {
|
||||
return this.modified;
|
||||
}
|
||||
|
||||
public void setModified(LocalDateTime modified) {
|
||||
public void setModified(OffsetDateTime modified) {
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import java.util.Set;
|
||||
|
||||
public interface User extends UserDetails {
|
||||
|
||||
Long getId();
|
||||
Integer getId();
|
||||
|
||||
String getEmail();
|
||||
void setEmail(String email);
|
||||
|
||||
@ -24,7 +24,7 @@ public final class UserEntity implements User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false)
|
||||
private Long id;
|
||||
private Integer id;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String username;
|
||||
@ -51,11 +51,11 @@ public final class UserEntity implements User {
|
||||
private Boolean credentialsExpired;
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@ -2,18 +2,19 @@ package app.mealsmadeeasy.api.user;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Entity(name = "UserGrantedAuthority")
|
||||
@Table(name = "user_granted_authority")
|
||||
public final class UserGrantedAuthorityEntity implements UserGrantedAuthority {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(nullable = false)
|
||||
private Long id;
|
||||
private Integer id;
|
||||
|
||||
private String authority;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_entity_id")
|
||||
@JoinColumn(name = "user_id")
|
||||
private UserEntity userEntity;
|
||||
|
||||
@Override
|
||||
|
||||
@ -11,14 +11,14 @@ public class UserInfoView {
|
||||
return userInfoView;
|
||||
}
|
||||
|
||||
private long id;
|
||||
private Integer id;
|
||||
private String username;
|
||||
|
||||
public long getId() {
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
spring.application.name=meals-made-easy-api
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:meals_made_easy_api}
|
||||
spring.datasource.username=${POSTGRES_USER:meals-made-easy-api-user}
|
||||
spring.datasource.password=${POSTGRES_PASSWORD}
|
||||
|
||||
108
src/main/resources/db/migration/V1__init_schema.sql
Normal file
108
src/main/resources/db/migration/V1__init_schema.sql
Normal file
@ -0,0 +1,108 @@
|
||||
CREATE TABLE "user" (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
locked BOOLEAN NOT NULL,
|
||||
expired BOOLEAN NOT NULL,
|
||||
enabled BOOLEAN NOT NULL,
|
||||
credentials_expired BOOLEAN NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE user_granted_authority (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id INT NOT NULL,
|
||||
authority VARCHAR(255),
|
||||
FOREIGN KEY (user_id) REFERENCES "user"
|
||||
);
|
||||
|
||||
CREATE TABLE refresh_token (
|
||||
token UUID PRIMARY KEY,
|
||||
issued TIMESTAMPTZ(6) NOT NULL,
|
||||
expiration TIMESTAMPTZ(6) NOT NULL,
|
||||
owner_id INT NOT NULL,
|
||||
deleted BOOLEAN NOT NULL,
|
||||
revoked BOOLEAN NOT NULL,
|
||||
FOREIGN KEY (owner_id) REFERENCES "user"
|
||||
);
|
||||
|
||||
CREATE TABLE image (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
created TIMESTAMPTZ(6) NOT NULL,
|
||||
modified TIMESTAMPTZ(6),
|
||||
|
||||
owner_id INT NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
|
||||
object_name VARCHAR(255) NOT NULL,
|
||||
user_filename VARCHAR(255) NOT NULL,
|
||||
mime_type VARCHAR(255) NOT NULL,
|
||||
alt VARCHAR(255),
|
||||
caption VARCHAR(255),
|
||||
|
||||
height INTEGER,
|
||||
width INTEGER,
|
||||
|
||||
FOREIGN KEY (owner_id) REFERENCES "user"
|
||||
);
|
||||
|
||||
CREATE TABLE image_viewer (
|
||||
image_id INT NOT NULL,
|
||||
viewer_id INT NOT NULL,
|
||||
PRIMARY KEY (image_id, viewer_id),
|
||||
FOREIGN KEY (image_id) REFERENCES image,
|
||||
FOREIGN KEY (viewer_id) REFERENCES "user"
|
||||
);
|
||||
|
||||
CREATE TABLE recipe (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
created TIMESTAMPTZ(6) NOT NULL,
|
||||
modified TIMESTAMPTZ(6),
|
||||
|
||||
owner_id INT NOT NULL,
|
||||
slug VARCHAR(255) NOT NULL,
|
||||
is_public BOOLEAN NOT NULL,
|
||||
|
||||
title VARCHAR(255) NOT NULL,
|
||||
raw_text TEXT NOT NULL,
|
||||
cached_rendered_text TEXT,
|
||||
main_image_id INT,
|
||||
|
||||
preparation_time INT,
|
||||
cooking_time INT,
|
||||
total_time INT,
|
||||
|
||||
FOREIGN KEY (owner_id) REFERENCES "user",
|
||||
FOREIGN KEY (main_image_id) REFERENCES image
|
||||
);
|
||||
|
||||
CREATE INDEX recipe_username_slug ON recipe (owner_id, slug);
|
||||
|
||||
CREATE TABLE recipe_viewer (
|
||||
recipe_id INT NOT NULL,
|
||||
viewer_id INT NOT NULL,
|
||||
PRIMARY KEY (recipe_id, viewer_id),
|
||||
FOREIGN KEY (recipe_id) REFERENCES recipe,
|
||||
FOREIGN KEY (viewer_id) REFERENCES "user"
|
||||
);
|
||||
|
||||
CREATE TABLE recipe_comment (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
created TIMESTAMPTZ(6) NOT NULL,
|
||||
modified TIMESTAMPTZ(6),
|
||||
owner_id INT NOT NULL,
|
||||
recipe_id INT NOT NULL,
|
||||
raw_text TEXT NOT NULL,
|
||||
cached_rendered_text TEXT,
|
||||
FOREIGN KEY (owner_id) REFERENCES "user",
|
||||
FOREIGN KEY (recipe_id) REFERENCES recipe
|
||||
);
|
||||
|
||||
CREATE TABLE recipe_star (
|
||||
timestamp TIMESTAMPTZ(6) NOT NULL,
|
||||
recipe_id INT NOT NULL,
|
||||
owner_id INT NOT NULL,
|
||||
PRIMARY KEY (recipe_id, owner_id),
|
||||
FOREIGN KEY (recipe_id) references recipe,
|
||||
FOREIGN KEY (owner_id) references "user"
|
||||
);
|
||||
@ -21,7 +21,7 @@ public class ContainsRecipeStarsMatcher extends ContainsItemsMatcher<RecipeStar,
|
||||
recipeStar -> ((RecipeStarEntity) recipeStar).getId(),
|
||||
recipeStar -> ((RecipeStarEntity) recipeStar).getId(),
|
||||
(id0, id1) -> Objects.equals(id0.getRecipeId(), id1.getRecipeId())
|
||||
&& Objects.equals(id0.getOwnerUsername(), id1.getOwnerUsername())
|
||||
&& Objects.equals(id0.getOwnerId(), id1.getOwnerId())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user