diff --git a/.github/workflows/JavaMavenCI.yml b/.github/workflows/JavaMavenCI.yml
new file mode 100644
index 0000000..690e6e9
--- /dev/null
+++ b/.github/workflows/JavaMavenCI.yml
@@ -0,0 +1,114 @@
+name: Java CI with Maven
+
+on:
+ pull_request:
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ cache: maven
+ - name: Compile with maven
+ run: mvn clean compile
+
+ - name: Update dependency graph
+ uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6
+
+ checkstyle:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ cache: maven
+ - name: Compile with maven
+ run: mvn checkstyle:check
+
+ testing:
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ cache: maven
+ - name: Compile maven project
+ run: mvn clean compile
+ - name: Test maven project
+ run: mvn test
+ - name: Add coverage to PR
+ id: jacoco
+ uses: madrapps/jacoco-report@v1.6.1
+ with:
+ paths: |
+ ${{ github.workspace }}/**/target/site/jacoco/*.xml
+ token: ${{ secrets.TEST_SECRET }}
+ min-coverage-overall: 50
+ min-coverage-changed-files: 50
+ - name: Upload coverage report
+ uses: actions/upload-artifact@v4
+ with:
+ name: jacoco-report
+ path: ${{ github.workspace }}/**/target/site/jacoco/
+
+ - name: Fail PR if overall coverage is less than 50%
+ if: ${{ steps.jacoco.outputs.coverage-overall < 50.0 }}
+ uses: actions/github-script@v6
+ with:
+ script: |
+ core.setFailed('Overall coverage is less than 50%!')
+
+ docker:
+ runs-on: ubuntu-latest
+ steps:
+ -
+ name: Checkout
+ uses: actions/checkout@v4
+ -
+ name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ cache: maven
+ -
+ name: Package
+ run: mvn clean package
+ -
+ name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+ -
+ name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ -
+ name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_PASSWORD }}
+ -
+ name: Build and push
+ uses: docker/build-push-action@v5
+ with:
+ context: ./api/.
+ push: true
+ tags: asavershin/api:latest
diff --git a/api/Dockerfile b/api/Dockerfile
index fd4a080..79aace5 100644
--- a/api/Dockerfile
+++ b/api/Dockerfile
@@ -1,4 +1,4 @@
-FROM openjdk:22
+FROM openjdk:21
WORKDIR /app
diff --git a/api/pom.xml b/api/pom.xml
index e145ce1..8fbee14 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -12,8 +12,8 @@
api
- 22
- 22
+ 21
+ 21
UTF-8
3.19.3
2.1.0
@@ -256,4 +256,5 @@
+
\ No newline at end of file
diff --git a/api/src/main/java/com/github/asavershin/api/ApiMain.java b/api/src/main/java/com/github/asavershin/api/ApiMain.java
index 5c2aba3..0ed4b22 100644
--- a/api/src/main/java/com/github/asavershin/api/ApiMain.java
+++ b/api/src/main/java/com/github/asavershin/api/ApiMain.java
@@ -1,11 +1,22 @@
package com.github.asavershin.api;
+
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+
@SpringBootApplication
public class ApiMain {
- public static void main(String[] args) {
+ /**
+ * The main method that starts the Spring Boot application.
+ *
+ * @param args the command-line arguments
+ */
+ public static void main(final String[] args) {
SpringApplication.run(ApiMain.class, args);
}
+
+ private void foo() {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/image/ImageService.java b/api/src/main/java/com/github/asavershin/api/application/in/services/image/ImageService.java
index de452c7..d2c4f5d 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/image/ImageService.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/image/ImageService.java
@@ -5,7 +5,29 @@
import org.springframework.web.multipart.MultipartFile;
public interface ImageService {
+ /**
+ * Stores an image for a given user.
+ *
+ * @param userId the user who owns the image
+ * @param multipartFile the image file to be stored
+ * @return the unique identifier of the stored image
+ */
ImageId storeImage(UserId userId, MultipartFile multipartFile);
+ /**
+ * Deletes an image by its unique identifier. Validate that
+ * image belongs to user.
+ *
+ * @param userId the user who owns the image
+ * @param imageId the unique identifier of the image to be deleted
+ */
void deleteImageByImageId(UserId userId, ImageId imageId);
+ /**
+ * Downloads an image by its unique identifier. Validate that
+ * image belongs to user.
+ *
+ * @param imageId the unique identifier of the image to be downloaded
+ * @param userId the user who owns the image
+ * @return the byte array representation of the image
+ */
byte[] downloadImage(ImageId imageId, UserId userId);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/ImageServiceImpl.java b/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/ImageServiceImpl.java
index 6f35ae9..eb2fc9a 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/ImageServiceImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/ImageServiceImpl.java
@@ -2,39 +2,67 @@
import com.github.asavershin.api.application.in.services.image.ImageService;
import com.github.asavershin.api.application.out.MinioService;
-import com.github.asavershin.api.common.Validator;
-import com.github.asavershin.api.domain.image.*;
+import com.github.asavershin.api.domain.image.DeleteImageOfUser;
+import com.github.asavershin.api.domain.image.GetImageOfUser;
+import com.github.asavershin.api.domain.image.Image;
+import com.github.asavershin.api.domain.image.ImageId;
+import com.github.asavershin.api.domain.image.ImageNameWithExtension;
+import com.github.asavershin.api.domain.image.MetaData;
+import com.github.asavershin.api.domain.image.StoreImageOfUser;
import com.github.asavershin.api.domain.user.UserId;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
-import java.util.Arrays;
+import java.io.Serializable;
import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
@Service
@RequiredArgsConstructor
-@Slf4j
-public class ImageServiceImpl implements ImageService {
+public class ImageServiceImpl implements ImageService, Serializable {
+ /**
+ * The MinioService is used to interact with the Minio storage service.
+ */
private final MinioService minioService;
+
+ /**
+ * The GetImageOfUser service is used to retrieve an image
+ * by its ID and user ID.
+ */
private final GetImageOfUser getImageOfUser;
+
+ /**
+ * The DeleteImageOfUser service is used to delete an image
+ * by its ID and user ID.
+ */
private final DeleteImageOfUser deleteImageOfUser;
+
+ /**
+ * The StoreImageOfUser service is used to store an image
+ * with its metadata and associate it with a user.
+ */
private final StoreImageOfUser storeImageOfUser;
+
+ /**
+ * Method not marked as final to allow Spring
+ * to create a proxy first for transactional purposes.
+ * @param userId the user who owns the image
+ * @param multipartFile the image file to be stored
+ * @return ID of new stored image
+ */
@Override
@Transactional
- public ImageId storeImage(UserId userId, MultipartFile multipartFile) {
- log.info("Store image: {}", multipartFile.getOriginalFilename());
- var metaInfo = new MetaInfo(
+ public ImageId storeImage(final UserId userId,
+ final MultipartFile multipartFile) {
+ var metaInfo = new MetaData(
ImageNameWithExtension
- .fromOriginalFileName(multipartFile.getOriginalFilename()),
+ .fromOriginalFileName(
+ multipartFile.getOriginalFilename()
+ ),
multipartFile.getSize()
);
- log.info("Store image: check on ex");
- var imageId = new ImageId(UUID.fromString(minioService.saveFile(multipartFile)));
+ var imageId = ImageId.nextIdentity();
storeImageOfUser.storeImageOfUser(
new Image(
imageId,
@@ -42,20 +70,39 @@ public ImageId storeImage(UserId userId, MultipartFile multipartFile) {
userId
)
);
+ minioService.saveFile(multipartFile, imageId.value().toString());
return imageId;
}
+ /**
+ * Method not marked as final to allow Spring
+ * * to create a proxy first for transactional purposes.
+ * @param userId the user who owns the image
+ * @param imageId the unique identifier of the image to be deleted
+ */
@Override
@Transactional
- public void deleteImageByImageId(UserId userId, ImageId imageId) {
+ public void deleteImageByImageId(final UserId userId,
+ final ImageId imageId) {
deleteImageOfUser.removeImageOfUser(imageId, userId);
minioService.deleteFiles(List.of(imageId.value().toString()));
}
+ /**
+ * Method not marked as final to allow Spring make CGLIB proxy.
+ * @param imageId the unique identifier of the image to be downloaded
+ * @param userId the user who owns the image
+ * @return bytes of the image
+ */
@Override
- public byte[] downloadImage(ImageId imageId, UserId userId) {
+ public byte[] downloadImage(final ImageId imageId,
+ final UserId userId) {
return minioService.getFile(
- getImageOfUser.getImageOfUser(userId, imageId).imageId().value().toString()
+ getImageOfUser.getImageOfUser(
+ userId,
+ imageId
+ )
+ .imageId().value().toString()
);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/package-info.java b/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/package-info.java
new file mode 100644
index 0000000..98dee3f
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/image/impl/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains implementation application services for images.
+ * @author asavershin
+ */
+package com.github.asavershin.api.application.in.services.image.impl;
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/image/package-info.java b/api/src/main/java/com/github/asavershin/api/application/in/services/image/package-info.java
new file mode 100644
index 0000000..9480e7d
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/image/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains application services for images.
+ * @author asavershin
+ */
+package com.github.asavershin.api.application.in.services.image;
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/ApplicationCredentials.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/ApplicationCredentials.java
index e8e288a..8ab9109 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/ApplicationCredentials.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/ApplicationCredentials.java
@@ -4,11 +4,26 @@
@Getter
public class ApplicationCredentials {
+ /**
+ * The access token for user.
+ */
private final String accessToken;
+
+ /**
+ * The refresh token for user.
+ */
private final String refreshToken;
- public ApplicationCredentials(String accessToken, String refreshToken) {
- this.accessToken = accessToken;
- this.refreshToken = refreshToken;
+ /**
+ * Constructs an instance of {@link ApplicationCredentials}
+ * with the provided access token and refresh token.
+ *
+ * @param aAccessToken The access token for user.
+ * @param aRefreshToken The refresh token for user.
+ */
+ public ApplicationCredentials(final String aAccessToken,
+ final String aRefreshToken) {
+ this.accessToken = aAccessToken;
+ this.refreshToken = aRefreshToken;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentials.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentials.java
index 7765672..cf788e9 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentials.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentials.java
@@ -4,5 +4,11 @@
@FunctionalInterface
public interface GetNewCredentials {
+ /**
+ * Generates new credentials for the user based on the provided credentials.
+ *
+ * @param credentials The current credentials of the user.
+ * @return The new credentials for the user.
+ */
ApplicationCredentials get(Credentials credentials);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentialsUsingRefreshToken.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentialsUsingRefreshToken.java
index f0ed0cc..1cdda6b 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentialsUsingRefreshToken.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/GetNewCredentialsUsingRefreshToken.java
@@ -4,5 +4,11 @@
@FunctionalInterface
public interface GetNewCredentialsUsingRefreshToken {
+ /**
+ * Generates new credentials using the provided refresh token.
+ *
+ * @param credentials The credentials that contain the refresh token.
+ * @return The new credentials generated using the refresh token.
+ */
ApplicationCredentials get(Credentials credentials);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/JwtService.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/JwtService.java
index 02e3646..ee436d2 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/JwtService.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/JwtService.java
@@ -4,11 +4,27 @@
public interface JwtService {
+ /**
+ * Generates an access token for the provided credentials.
+ *
+ * @param credentials The credentials used to generate the access token.
+ * @return A string representing the generated access token.
+ */
String generateAccessToken(Credentials credentials);
- String generateRefreshToken(
- Credentials credentials
- );
+ /**
+ * Generates a refresh token for the provided credentials.
+ *
+ * @param credentials The credentials used to generate the refresh token.
+ * @return A string representing the generated refresh token.
+ */
+ String generateRefreshToken(Credentials credentials);
+ /**
+ * Extracts the subject from the provided JWT.
+ *
+ * @param jwt The JWT from which the subject should be extracted.
+ * @return A string representing the extracted subject.
+ */
String extractSub(String jwt);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsImpl.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsImpl.java
index 75a5838..71b306f 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsImpl.java
@@ -15,20 +15,38 @@
@RequiredArgsConstructor
@Slf4j
public class GetNewCredentialsImpl implements GetNewCredentials {
+ /**
+ * Dependency for get,save,delete tokens in redis.
+ */
private final TokenRepository tokenRepository;
+ /**
+ * Domain service that allow user try to log in.
+ */
private final TryToLogin tryToLogin;
+ /**
+ * Application service that allow to do some manipulations with JWT tokens.
+ */
private final JwtService jwtService;
+ /**
+ * Property that contains secret and access, refresh expirations.
+ */
private final JwtProperties jwtProperties;
@Override
- public ApplicationCredentials get(Credentials credentials) {
+ public final ApplicationCredentials get(final Credentials credentials) {
var authenticatedUser = tryToLogin.login(credentials);
- var accessToken = jwtService.generateAccessToken(authenticatedUser.userCredentials());
- var refreshToken = jwtService.generateRefreshToken(authenticatedUser.userCredentials());
+ var accessToken = jwtService
+ .generateAccessToken(authenticatedUser.userCredentials());
+ var refreshToken = jwtService
+ .generateRefreshToken(authenticatedUser.userCredentials());
var email = authenticatedUser.userCredentials().email();
tokenRepository.deleteAllTokensByUserEmail(email);
- tokenRepository.saveRefreshToken(email, refreshToken, jwtProperties.getRefreshExpiration());
- tokenRepository.saveAccessToken(email, accessToken, jwtProperties.getAccessExpiration());
+ tokenRepository.saveRefreshToken(email,
+ refreshToken,
+ jwtProperties.getRefreshExpiration());
+ tokenRepository.saveAccessToken(email,
+ accessToken,
+ jwtProperties.getAccessExpiration());
return new ApplicationCredentials(accessToken, refreshToken);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsUsingRefreshTokenImpl.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsUsingRefreshTokenImpl.java
index 1d16949..7a057b0 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsUsingRefreshTokenImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/GetNewCredentialsUsingRefreshTokenImpl.java
@@ -11,18 +11,40 @@
@Service
@RequiredArgsConstructor
-public class GetNewCredentialsUsingRefreshTokenImpl implements GetNewCredentialsUsingRefreshToken {
+public class GetNewCredentialsUsingRefreshTokenImpl
+ implements GetNewCredentialsUsingRefreshToken {
+ /**
+ * The repository for storing and retrieving tokens.
+ */
private final TokenRepository tokenRepository;
+
+ /**
+ * The service for generating and validating JWT tokens.
+ */
private final JwtService jwtService;
- private final JwtProperties jwtProperties;
+ /**
+ * The properties containing the configuration for JWT tokens.
+ */
+ private final JwtProperties jwtProperties;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public ApplicationCredentials get(Credentials credentials) {
+ public ApplicationCredentials get(final Credentials credentials) {
tokenRepository.deleteAllTokensByUserEmail(credentials.email());
var at = jwtService.generateAccessToken(credentials);
var rt = jwtService.generateRefreshToken(credentials);
- tokenRepository.saveAccessToken(credentials.email(), at, jwtProperties.getAccessExpiration());
- tokenRepository.saveRefreshToken(credentials.email(), rt, jwtProperties.getRefreshExpiration());
+ tokenRepository.saveAccessToken(
+ credentials.email(),
+ at,
+ jwtProperties.getAccessExpiration()
+ );
+ tokenRepository.saveRefreshToken(
+ credentials.email(),
+ rt,
+ jwtProperties.getRefreshExpiration()
+ );
return new ApplicationCredentials(at, rt);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/JwtServiceIml.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/JwtServiceIml.java
index c229ea7..675b938 100644
--- a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/JwtServiceIml.java
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/JwtServiceIml.java
@@ -2,7 +2,6 @@
import com.github.asavershin.api.application.in.services.user.JwtService;
import com.github.asavershin.api.config.properties.JwtProperties;
-import com.github.asavershin.api.domain.user.AuthenticatedUser;
import com.github.asavershin.api.domain.user.Credentials;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@@ -18,20 +17,30 @@
@RequiredArgsConstructor
public class JwtServiceIml implements JwtService {
+ /**
+ * The JwtProperties object contains the properties
+ * for generating and validating JWT tokens.
+ */
private final JwtProperties jwtProperties;
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public String generateAccessToken(Credentials credentials) {
+ public String generateAccessToken(final Credentials credentials) {
return buildToken(credentials, jwtProperties.getAccessExpiration());
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public String generateRefreshToken(Credentials credentials) {
+ public String generateRefreshToken(final Credentials credentials) {
return buildToken(credentials, jwtProperties.getRefreshExpiration());
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public String extractSub(String jwt) {
+ public String extractSub(final String jwt) {
return Jwts.parserBuilder()
.setSigningKey(getSignInKey())
.build()
@@ -40,12 +49,15 @@ public String extractSub(String jwt) {
.getSubject();
}
- private String buildToken(Credentials credentials, long expiration) {
+ private String buildToken(final Credentials credentials,
+ final long expiration) {
return Jwts
.builder()
.setSubject(credentials.email())
.setIssuedAt(new Date(System.currentTimeMillis()))
- .setExpiration(new Date(System.currentTimeMillis() + expiration))
+ .setExpiration(
+ new Date(System.currentTimeMillis() + expiration)
+ )
.signWith(getSignInKey(), SignatureAlgorithm.HS256)
.compact();
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/package-info.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/package-info.java
new file mode 100644
index 0000000..b0db315
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/impl/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains implementation application services for users.
+ * @author asavershin
+ */
+package com.github.asavershin.api.application.in.services.user.impl;
diff --git a/api/src/main/java/com/github/asavershin/api/application/in/services/user/package-info.java b/api/src/main/java/com/github/asavershin/api/application/in/services/user/package-info.java
new file mode 100644
index 0000000..6bdc8a8
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/application/in/services/user/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains application services for users.
+ * @author asavershin
+ */
+package com.github.asavershin.api.application.in.services.user;
diff --git a/api/src/main/java/com/github/asavershin/api/application/out/CacheRepository.java b/api/src/main/java/com/github/asavershin/api/application/out/CacheRepository.java
index 7ba8d35..8c22291 100644
--- a/api/src/main/java/com/github/asavershin/api/application/out/CacheRepository.java
+++ b/api/src/main/java/com/github/asavershin/api/application/out/CacheRepository.java
@@ -1,9 +1,28 @@
package com.github.asavershin.api.application.out;
public interface CacheRepository {
+ /**
+ * Adds a cache entry with the specified key,
+ * token, and expiration time.
+ *
+ * @param key the unique identifier for the cache entry
+ * @param token the token associated with the cache entry
+ * @param expiration the time in milliseconds after
+ * which the cache entry will expire
+ */
void addCache(String key, String token, long expiration);
-
+ /**
+ * Retrieves the cache entry associated with the specified key.
+ *
+ * @param key the unique identifier for the cache entry
+ * @return the token associated with the cache entry,
+ * or null if the entry does not exist or has expired
+ */
String getCache(String key);
-
+ /**
+ * Deletes the cache entry associated with the specified key.
+ *
+ * @param key the unique identifier for the cache entry
+ */
void deleteCache(String key);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/out/FileService.java b/api/src/main/java/com/github/asavershin/api/application/out/FileService.java
index fb837cb..2691519 100644
--- a/api/src/main/java/com/github/asavershin/api/application/out/FileService.java
+++ b/api/src/main/java/com/github/asavershin/api/application/out/FileService.java
@@ -2,8 +2,26 @@
import java.util.List;
-public interface FileService {
- T saveFile(K file);
+public interface FileService {
+ /**
+ * Saves a file to the storage.
+ *
+ * @param file The file object to be saved.
+ * @param filename The name of the file to be saved.
+ * Must be unique.
+ */
+ void saveFile(K file, String filename);
+ /**
+ * Retrieves the content of a file from the storage.
+ *
+ * @param link The unique identifier or link of the file.
+ * @return The content of the file as a byte array.
+ */
byte[] getFile(String link);
+ /**
+ * Deletes multiple files from the storage.
+ *
+ * @param files A list of file links to be deleted.
+ */
void deleteFiles(List files);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/out/MinioService.java b/api/src/main/java/com/github/asavershin/api/application/out/MinioService.java
index b829a63..93835cb 100644
--- a/api/src/main/java/com/github/asavershin/api/application/out/MinioService.java
+++ b/api/src/main/java/com/github/asavershin/api/application/out/MinioService.java
@@ -2,5 +2,5 @@
import org.springframework.web.multipart.MultipartFile;
-public interface MinioService extends FileService{
+public interface MinioService extends FileService {
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/out/TokenRepository.java b/api/src/main/java/com/github/asavershin/api/application/out/TokenRepository.java
index d57436b..2f03cb0 100644
--- a/api/src/main/java/com/github/asavershin/api/application/out/TokenRepository.java
+++ b/api/src/main/java/com/github/asavershin/api/application/out/TokenRepository.java
@@ -1,13 +1,46 @@
package com.github.asavershin.api.application.out;
public interface TokenRepository {
+ /**
+ * Retrieves the access token for the given email.
+ *
+ * @param email the email of the user
+ * @return the access token for the given email
+ */
String getAccessToken(String email);
+ /**
+ * Retrieves the refresh token for the given email.
+ *
+ * @param email the email of the user
+ * @return the refresh token for the given email
+ */
String getRefreshToken(String email);
+ /**
+ * Saves the refresh token for the given user with
+ * the specified JWT token and expiration time.
+ *
+ * @param username the username of the user
+ * @param jwtToken the JWT token to be saved
+ * @param expiration the expiration time of the token
+ */
void saveRefreshToken(String username, String jwtToken, Long expiration);
+ /**
+ * Saves the access token for the given user with
+ * the specified JWT token and expiration time.
+ *
+ * @param username the username of the user
+ * @param jwtToken the JWT token to be saved
+ * @param expiration the expiration time of the token
+ */
void saveAccessToken(String username, String jwtToken, Long expiration);
+ /**
+ * Deletes all tokens associated with the given user email.
+ *
+ * @param username the username of the user
+ */
void deleteAllTokensByUserEmail(String username);
}
diff --git a/api/src/main/java/com/github/asavershin/api/application/out/package-info.java b/api/src/main/java/com/github/asavershin/api/application/out/package-info.java
new file mode 100644
index 0000000..c70aea2
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/application/out/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains storage interfaces that are not domain specific.
+ * @author asavershin
+ */
+package com.github.asavershin.api.application.out;
diff --git a/api/src/main/java/com/github/asavershin/api/common/NotFoundException.java b/api/src/main/java/com/github/asavershin/api/common/NotFoundException.java
index 2584611..a2a8110 100644
--- a/api/src/main/java/com/github/asavershin/api/common/NotFoundException.java
+++ b/api/src/main/java/com/github/asavershin/api/common/NotFoundException.java
@@ -1,7 +1,10 @@
package com.github.asavershin.api.common;
-public class NotFoundException extends RuntimeException{
- public NotFoundException(String message){
+public class NotFoundException extends RuntimeException {
+ /**
+ * @param message specifies information about the object not found
+ */
+ public NotFoundException(final String message) {
super(message);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/common/Validator.java b/api/src/main/java/com/github/asavershin/api/common/Validator.java
index afd6770..f0f70dc 100644
--- a/api/src/main/java/com/github/asavershin/api/common/Validator.java
+++ b/api/src/main/java/com/github/asavershin/api/common/Validator.java
@@ -2,45 +2,138 @@
import java.util.Objects;
-public class Validator {
- public static void assertArgumentLength(String aString, int aMinimum, int aMaximum, String aMessage) {
+/**
+ * A utility class for performing basic validation checks.
+ *
+ * @author asavershin
+ */
+public abstract class Validator {
+
+ /**
+ * Asserts that the given string has a length within
+ * the specified range.
+ *
+ * @param aString the string to validate
+ * @param aMinimum the minimum length
+ * @param aMaximum the maximum length
+ * @param aMessage the message to throw if the length is invalid
+ * @throws IllegalArgumentException if the length of the string
+ * is less than {@code aMinimum} or greater than {@code aMaximum}
+ */
+ public static void assertArgumentLength(final String aString,
+ final int aMinimum,
+ final int aMaximum,
+ final String aMessage) {
int length = aString.length();
if (length < aMinimum || length > aMaximum) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertArgumentLength(String aString, int aMinimum, String aMessage) {
+ /**
+ * Asserts that the given string has a length greater than or equal
+ * to the specified minimum.
+ *
+ * @param aString the string to validate
+ * @param aMinimum the minimum length
+ * @param aMessage the message to throw if the length is invalid
+ * @throws IllegalArgumentException if the length of the string is
+ * less than {@code aMinimum}
+ */
+ public static void assertArgumentLength(final String aString,
+ final int aMinimum,
+ final String aMessage) {
int length = aString.length();
if (length < aMinimum) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertStringFormat(String email, String regex, String aMessage) {
+ /**
+ * Asserts that the given string matches the specified regular
+ * expression.
+ *
+ * @param email the string to validate
+ * @param regex the regular expression to match against
+ * @param aMessage the message to throw if the string does not
+ * match the regular expression
+ * @throws IllegalArgumentException if the string does not
+ * match the regular expression
+ */
+ public static void assertStringFormat(final String email,
+ final String regex,
+ final String aMessage) {
if (!email.matches(regex)) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertArrayLength(Object[] array, Integer minLength, String aMessage) {
+ /**
+ * Asserts that the given array has a length greater than or
+ * equal to the specified minimum.
+ *
+ * @param array the array to validate
+ * @param minLength the minimum length
+ * @param aMessage the message to throw if the length of the
+ * array is less than {@code minLength}
+ * @throws IllegalArgumentException if the length of the array
+ * is less than {@code minLength}
+ */
+ public static void assertArrayLength(final Object[] array,
+ final Integer minLength,
+ final String aMessage) {
if (array.length < minLength) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertLongSize(Long value, Long minLength, Long maxLength, String aMessage) {
+ /**
+ * Asserts that the given value is within the specified range.
+ *
+ * @param value the value to validate
+ * @param minLength the minimum length
+ * @param maxLength the maximum length
+ * @param aMessage the message to throw if the value is outside
+ * the specified range
+ * @throws IllegalArgumentException if the value is less than
+ * {@code minLength} or greater than {@code maxLength}
+ */
+ public static void assertLongSize(final Long value,
+ final Long minLength,
+ final Long maxLength,
+ final String aMessage) {
if (value < minLength || value > maxLength) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertLongSize(Long value, Long minLength, String aMessage) {
+ /**
+ * Asserts that the given value is greater than or equal to the
+ * specified minimum.
+ *
+ * @param value the value to validate
+ * @param minLength the minimum length
+ * @param aMessage the message to throw if the value is less
+ * than {@code minLength}
+ * @throws IllegalArgumentException if the value is less
+ * than {@code minLength}
+ */
+ public static void assertLongSize(final Long value,
+ final Long minLength,
+ final String aMessage) {
if (value < minLength) {
throw new IllegalArgumentException(aMessage);
}
}
- public static void assertNotFound(Object object, String aMessage) {
+ /**
+ * Asserts that the given object is not null.
+ *
+ * @param object the object to validate
+ * @param aMessage the message to throw if the object is null
+ * @throws IllegalArgumentException if the object is null
+ */
+ public static void assertNotFound(final Object object,
+ final String aMessage) {
if (Objects.isNull(object)) {
throw new NotFoundException(aMessage);
}
diff --git a/api/src/main/java/com/github/asavershin/api/common/annotations/Command.java b/api/src/main/java/com/github/asavershin/api/common/annotations/Command.java
index 0725e3a..51b88d9 100644
--- a/api/src/main/java/com/github/asavershin/api/common/annotations/Command.java
+++ b/api/src/main/java/com/github/asavershin/api/common/annotations/Command.java
@@ -1,6 +1,10 @@
package com.github.asavershin.api.common.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Inherited;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
diff --git a/api/src/main/java/com/github/asavershin/api/common/annotations/DomainService.java b/api/src/main/java/com/github/asavershin/api/common/annotations/DomainService.java
index 6b0666c..30f2f55 100644
--- a/api/src/main/java/com/github/asavershin/api/common/annotations/DomainService.java
+++ b/api/src/main/java/com/github/asavershin/api/common/annotations/DomainService.java
@@ -1,6 +1,10 @@
package com.github.asavershin.api.common.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Inherited;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
diff --git a/api/src/main/java/com/github/asavershin/api/common/annotations/Query.java b/api/src/main/java/com/github/asavershin/api/common/annotations/Query.java
index 1d1483d..1b83bf0 100644
--- a/api/src/main/java/com/github/asavershin/api/common/annotations/Query.java
+++ b/api/src/main/java/com/github/asavershin/api/common/annotations/Query.java
@@ -1,6 +1,10 @@
package com.github.asavershin.api.common.annotations;
-import java.lang.annotation.*;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Inherited;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
diff --git a/api/src/main/java/com/github/asavershin/api/common/annotations/package-info.java b/api/src/main/java/com/github/asavershin/api/common/annotations/package-info.java
new file mode 100644
index 0000000..15967d2
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/common/annotations/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package annotations for classes that characterize their activities.
+ * @author asavershin
+ */
+package com.github.asavershin.api.common.annotations;
diff --git a/api/src/main/java/com/github/asavershin/api/common/package-info.java b/api/src/main/java/com/github/asavershin/api/common/package-info.java
new file mode 100644
index 0000000..74606bc
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/common/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * This package contains code that could be useful for coding.
+ * It contains validators and exceptions that often found.
+ * It annotations for classes that characterize their activities.
+ * @author asavershin
+ */
+package com.github.asavershin.api.common;
diff --git a/api/src/main/java/com/github/asavershin/api/config/AnnotationsConfig.java b/api/src/main/java/com/github/asavershin/api/config/AnnotationsConfig.java
index 216bfe6..6a084c2 100644
--- a/api/src/main/java/com/github/asavershin/api/config/AnnotationsConfig.java
+++ b/api/src/main/java/com/github/asavershin/api/config/AnnotationsConfig.java
@@ -11,9 +11,12 @@
@ComponentScan(
basePackages = "com.github.asavershin.api",
includeFilters = {
- @ComponentScan.Filter(type = FilterType.ANNOTATION, value = DomainService.class),
- @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Query.class),
- @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Command.class)
+ @ComponentScan.Filter(type = FilterType.ANNOTATION,
+ value = DomainService.class),
+ @ComponentScan.Filter(type = FilterType.ANNOTATION,
+ value = Query.class),
+ @ComponentScan.Filter(type = FilterType.ANNOTATION,
+ value = Command.class)
}
)
public class AnnotationsConfig {
diff --git a/api/src/main/java/com/github/asavershin/api/config/AuthConfig.java b/api/src/main/java/com/github/asavershin/api/config/AuthConfig.java
index d72aeb3..69da912 100644
--- a/api/src/main/java/com/github/asavershin/api/config/AuthConfig.java
+++ b/api/src/main/java/com/github/asavershin/api/config/AuthConfig.java
@@ -3,17 +3,17 @@
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
-import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
-import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@RequiredArgsConstructor
public class AuthConfig {
+ /**
+ * Configures a BCryptPasswordEncoder bean for password encoding.
+ *
+ * @return a new instance of BCryptPasswordEncoder
+ */
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
diff --git a/api/src/main/java/com/github/asavershin/api/config/MinIOConfig.java b/api/src/main/java/com/github/asavershin/api/config/MinIOConfig.java
index 7bb2900..3249974 100644
--- a/api/src/main/java/com/github/asavershin/api/config/MinIOConfig.java
+++ b/api/src/main/java/com/github/asavershin/api/config/MinIOConfig.java
@@ -7,14 +7,29 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+/**
+ * Configuration class for MinIO client.
+ *
+ * @author Asavershin
+ */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class MinIOConfig {
+
+ /**
+ * The MinIO properties.
+ */
private final MinIOProperties minioProperties;
+
+ /**
+ * Creates a MinioClient instance.
+ *
+ * @return A MinioClient instance configured with the provided
+ * MinIO properties.
+ */
@Bean
public MinioClient minioClient() {
- log.info("MinIOConfigLog");
log.info(minioProperties.toString());
return MinioClient.builder()
.endpoint(minioProperties.getUrl())
diff --git a/api/src/main/java/com/github/asavershin/api/config/RedisConfig.java b/api/src/main/java/com/github/asavershin/api/config/RedisConfig.java
index 5003bf1..5b920ef 100644
--- a/api/src/main/java/com/github/asavershin/api/config/RedisConfig.java
+++ b/api/src/main/java/com/github/asavershin/api/config/RedisConfig.java
@@ -7,14 +7,30 @@
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
+/**
+ * Configuration class for setting up the RedisTemplate.
+ *
+ * @author Asavershin
+ */
@Configuration
public class RedisConfig {
+
+ /**
+ * Creates a new instance of {@link RedisTemplate} with the provided
+ * {@link RedisConnectionFactory}.
+ *
+ * @param connectionFactory the RedisConnectionFactory to use
+ * @return a new instance of {@link RedisTemplate}
+ */
@Bean
- public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
+ public RedisTemplate redisTemplate(
+ final RedisConnectionFactory connectionFactory) {
final RedisTemplate template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
- template.setValueSerializer(new GenericToStringSerializer<>(Object.class));
+ template.setValueSerializer(
+ new GenericToStringSerializer<>(Object.class)
+ );
return template;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/config/package-info.java b/api/src/main/java/com/github/asavershin/api/config/package-info.java
new file mode 100644
index 0000000..3d5fb9e
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/config/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains configs for infrastructure of service.
+ * @author asavershin
+ */
+package com.github.asavershin.api.config;
diff --git a/api/src/main/java/com/github/asavershin/api/config/properties/JwtProperties.java b/api/src/main/java/com/github/asavershin/api/config/properties/JwtProperties.java
index 22f8438..5cb2e2b 100644
--- a/api/src/main/java/com/github/asavershin/api/config/properties/JwtProperties.java
+++ b/api/src/main/java/com/github/asavershin/api/config/properties/JwtProperties.java
@@ -1,16 +1,30 @@
package com.github.asavershin.api.config.properties;
import lombok.Data;
-import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
+@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
- @Value("${jwt.secret}")
+ /**
+ * Secret key used for signing JWT tokens.
+ */
private String secret;
- @Value("${jwt.access-expiration}")
+
+ /**
+ * Expiration time for access tokens in milliseconds.
+ */
private Long accessExpiration;
- @Value("${jwt.refresh-expiration}")
+
+ /**
+ * Expiration time for refresh tokens in milliseconds.
+ */
private Long refreshExpiration;
+
+ /**
+ * Constants for the start of the token in the Authorization header.
+ */
+ public static final int START_OF_TOKEN = 7;
}
diff --git a/api/src/main/java/com/github/asavershin/api/config/properties/MinIOProperties.java b/api/src/main/java/com/github/asavershin/api/config/properties/MinIOProperties.java
index 7369083..805e730 100644
--- a/api/src/main/java/com/github/asavershin/api/config/properties/MinIOProperties.java
+++ b/api/src/main/java/com/github/asavershin/api/config/properties/MinIOProperties.java
@@ -1,8 +1,8 @@
package com.github.asavershin.api.config.properties;
-import lombok.*;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@@ -10,8 +10,23 @@
@ConfigurationProperties(prefix = "minio")
@NoArgsConstructor
public class MinIOProperties {
+ /**
+ * The name of the bucket in the MinIO service.
+ */
private String bucket;
+
+ /**
+ * The URL of the MinIO service.
+ */
private String url;
+
+ /**
+ * The username for the MinIO service.
+ */
private String user;
+
+ /**
+ * The password for the MinIO service.
+ */
private String password;
}
diff --git a/api/src/main/java/com/github/asavershin/api/config/properties/UserProperties.java b/api/src/main/java/com/github/asavershin/api/config/properties/UserProperties.java
new file mode 100644
index 0000000..a4bbd51
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/config/properties/UserProperties.java
@@ -0,0 +1,18 @@
+package com.github.asavershin.api.config.properties;
+
+public final class UserProperties {
+ /**
+ * Minimum password length.
+ */
+ public static final int MIN_PASSWORD_LENGTH = 8;
+ /**
+ * Maximum firstname length.
+ */
+ public static final int MAX_FIRSTNAME_LENGTH = 20;
+ /**
+ * Maximum lastname length.
+ */
+ public static final int MAX_LASTNAME_LENGTH = 20;
+
+ private UserProperties() { }
+}
diff --git a/api/src/main/java/com/github/asavershin/api/config/properties/package-info.java b/api/src/main/java/com/github/asavershin/api/config/properties/package-info.java
new file mode 100644
index 0000000..1109013
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/config/properties/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * This package contains parameters that can be used in different
+ * parts of the application. The values are taken from .yml/.properties file
+ * @author asavershin
+ */
+package com.github.asavershin.api.config.properties;
diff --git a/api/src/main/java/com/github/asavershin/api/domain/IsEntityFound.java b/api/src/main/java/com/github/asavershin/api/domain/IsEntityFound.java
index 9aca1af..837edcf 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/IsEntityFound.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/IsEntityFound.java
@@ -3,7 +3,10 @@
import com.github.asavershin.api.common.Validator;
public abstract class IsEntityFound {
- protected void isEntityFound(Object entity, String entityName, String idName, String entityId){
+ protected final void isEntityFound(final Object entity,
+ final String entityName,
+ final String idName,
+ final String entityId) {
Validator.assertNotFound(entity,
entityName + " with " + idName + entityId + " not found");
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/PartOfResources.java b/api/src/main/java/com/github/asavershin/api/domain/PartOfResources.java
index 0c8262f..1c0f0ba 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/PartOfResources.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/PartOfResources.java
@@ -4,12 +4,37 @@
import java.util.Objects;
+/**
+ * A record representing a part of resources to be fetched from a
+ * data source.
+ * It contains the page number and the page size for pagination purposes.
+ *
+ * @param pageNumber The zero-based index of the first record
+ * to retrieve.
+ * @param pageSize The maximum number of records to retrieve.
+ */
public record PartOfResources(Long pageNumber, Long pageSize) {
- public PartOfResources{
- Objects.requireNonNull(pageNumber, "PageNumber must not be empty");
- Objects.requireNonNull(pageSize, "PageSize must not be empty");
- Validator.assertLongSize(pageNumber, 0L, "PageNumber must not be negative");
- if(pageSize <= 0)
- throw new IllegalArgumentException("PageSize must be positive");
+
+ /**
+ * Constructor for the PartOfResources record.
+ *
+ * @param pageNumber The zero-based index of the first record
+ * to retrieve.
+ * @param pageSize The maximum number of records to retrieve.
+ * @throws IllegalArgumentException if the pageSize is less than
+ * or equal to zero.
+ */
+ public PartOfResources {
+ Objects.requireNonNull(pageNumber,
+ "PageNumber must not be empty");
+ Objects.requireNonNull(pageSize,
+ "PageSize must not be empty");
+ Validator.assertLongSize(pageNumber,
+ 0L, "PageNumber must not be negative");
+ Validator.assertLongSize(
+ pageSize,
+ 1L,
+ "PageSize must be positive"
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/ResourceOwnershipException.java b/api/src/main/java/com/github/asavershin/api/domain/ResourceOwnershipException.java
index b9395ee..3db43d2 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/ResourceOwnershipException.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/ResourceOwnershipException.java
@@ -1,7 +1,20 @@
package com.github.asavershin.api.domain;
+/**
+ * Represents an exception that is thrown
+ * when there is an issue with resource ownership.
+ * For example, a user requests someone else's picture
+ * @author Asavershin
+ */
public class ResourceOwnershipException extends RuntimeException {
- public ResourceOwnershipException(String message) {
+
+ /**
+ * Constructs a new instance of the ResourceOwnershipException
+ * with the specified error message.
+ *
+ * @param message the error message
+ */
+ public ResourceOwnershipException(final String message) {
super(message);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/DeleteImageOfUser.java b/api/src/main/java/com/github/asavershin/api/domain/image/DeleteImageOfUser.java
index 4b425b0..404c0ab 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/DeleteImageOfUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/DeleteImageOfUser.java
@@ -4,5 +4,11 @@
@FunctionalInterface
public interface DeleteImageOfUser {
+ /**
+ * Removes the specified image of the specified user.
+ *
+ * @param imageId the unique identifier of the image to be removed
+ * @param userId the unique identifier of the user who owns the image
+ */
void removeImageOfUser(ImageId imageId, UserId userId);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/GetImageOfUser.java b/api/src/main/java/com/github/asavershin/api/domain/image/GetImageOfUser.java
index ce7911c..a116ae6 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/GetImageOfUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/GetImageOfUser.java
@@ -4,5 +4,12 @@
@FunctionalInterface
public interface GetImageOfUser {
+ /**
+ * Method that retrieves an image of a user.
+ *
+ * @param userId the unique identifier of the user
+ * @param imageId the unique identifier of the image
+ * @return the image of the specified user
+ */
Image getImageOfUser(UserId userId, ImageId imageId);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/GetPartImagesOfUser.java b/api/src/main/java/com/github/asavershin/api/domain/image/GetPartImagesOfUser.java
index 534413f..db0cb2b 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/GetPartImagesOfUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/GetPartImagesOfUser.java
@@ -7,5 +7,14 @@
@FunctionalInterface
public interface GetPartImagesOfUser {
+ /**
+ * This interface represents a function that retrieves a list of
+ * images for a specific user and part of resources.
+ *
+ * @param userId the unique identifier of the user
+ * @param partOfResources pagination
+ * @return a list of images belonging to the specified
+ * user and part of resources as pagination
+ */
List get(UserId userId, PartOfResources partOfResources);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/Image.java b/api/src/main/java/com/github/asavershin/api/domain/image/Image.java
index b6a9c90..f8c7063 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/Image.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/Image.java
@@ -1,6 +1,5 @@
package com.github.asavershin.api.domain.image;
-import com.github.asavershin.api.domain.IsEntityFound;
import com.github.asavershin.api.domain.ResourceOwnershipException;
import com.github.asavershin.api.domain.user.UserId;
import lombok.EqualsAndHashCode;
@@ -13,36 +12,68 @@
@Getter
@EqualsAndHashCode
public class Image {
+ /**
+ * The unique identifier for the image.
+ */
private ImageId imageId;
- private MetaInfo metaInfo;
+
+ /**
+ * The meta information associated with the image.
+ */
+ private MetaData metaInfo;
+
+ /**
+ * The user who owns the image.
+ */
private UserId userId;
- public Image(ImageId imageId, MetaInfo metaInfo, UserId userId){
- setImageId(imageId);
- setMetaInfo(metaInfo);
- setUserId(userId);
+
+ /**
+ * Constructor for creating a new Image object.
+ *
+ * @param aImageId the unique identifier for the image
+ * @param aMetaInfo the meta information associated with the image
+ * @param aUserId the user who owns the image
+ */
+ public Image(final ImageId aImageId,
+ final MetaData aMetaInfo,
+ final UserId aUserId) {
+ setImageId(aImageId);
+ setMetaInfo(aMetaInfo);
+ setUserId(aUserId);
}
- public Image belongsToUser(UserId userId){
- if (!this.userId.equals(userId)){
+ /**
+ * Checks if the given user owns the image.
+ *
+ * @param aUserId the user to check ownership for
+ * @return the same image instance if the user owns the image,
+ * otherwise throws a {@link ResourceOwnershipException}
+ * @throws ResourceOwnershipException if the image does not belong
+ * to the given user
+ */
+ public Image belongsToUser(final UserId aUserId) {
+ if (!this.userId.equals(aUserId)) {
throw new ResourceOwnershipException(
- "Image with id " + imageId.value().toString()+ " does not belong to user with id " + userId.value().toString()
+ "Image with id " + imageId.value().toString()
+ + " does not belong to user with id "
+ + aUserId.value().toString()
);
}
return this;
}
- private void setImageId(ImageId imageId) {
- Objects.requireNonNull(imageId, "ImageId must not be null");
- this.imageId = imageId;
+ private void setImageId(final ImageId aImageId) {
+ Objects.requireNonNull(aImageId, "ImageId must not be null");
+ this.imageId = aImageId;
}
- private void setMetaInfo(MetaInfo metaInfo) {
- Objects.requireNonNull(metaInfo, "MetaInfo must not be null");
- this.metaInfo = metaInfo;
+ private void setMetaInfo(final MetaData aMetaInfo) {
+ Objects.requireNonNull(aMetaInfo, "MetaInfo must not be null");
+ this.metaInfo = aMetaInfo;
}
- private void setUserId(UserId userId) {
- Objects.requireNonNull(userId, "UserId must not be null");
- this.userId = userId;
+ private void setUserId(final UserId aUserId) {
+ Objects.requireNonNull(aUserId, "UserId must not be null");
+ this.userId = aUserId;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/ImageExtension.java b/api/src/main/java/com/github/asavershin/api/domain/image/ImageExtension.java
index 91b163f..2b367f1 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/ImageExtension.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/ImageExtension.java
@@ -1,20 +1,39 @@
package com.github.asavershin.api.domain.image;
-import lombok.EqualsAndHashCode;
-
import java.util.Map;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;
+
+/**
+ * Enum representing different image file extensions.
+ *
+ * @author asavershin
+ */
public enum ImageExtension {
+ /**
+ * Represents the JPG image file extension.
+ */
JPG(".jpg"),
+
+ /**
+ * Represents the PNG image file extension.
+ */
PNG(".png"),
- JPEG(".jpeg");
+ /**
+ * Represents the JPEG image file extension.
+ */
+ JPEG(".jpeg");
+ /**
+ * Represents the string image file extension
+ * in format .extension.
+ */
private final String extension;
- private ImageExtension(String extension){
- this.extension = extension;
+
+ ImageExtension(final String aExtension) {
+ this.extension = aExtension;
}
@Override
@@ -22,13 +41,29 @@ public String toString() {
return extension;
}
- private static final Map stringToEnum
+ /**
+ * Map that stores a string representation of an extension in keys,
+ * and their corresponding ENUM in values.
+ */
+ private static final Map STRING_TO_ENUM
= Stream.of(values()).collect(toMap(Object::toString, e -> e));
- public static ImageExtension fromString(String extension){
- var imageExtension = stringToEnum.get(extension);
- if(imageExtension == null){
- throw new IllegalArgumentException("Invalid extension: " + extension);
+ /**
+ * Converts a string representation of an image extension
+ * to the corresponding enum instance.
+ *
+ * @param extension the string representation of the image extension
+ * @return the enum instance corresponding to the given
+ * string representation
+ * @throws IllegalArgumentException if the given string representation
+ * does not match any known image extension
+ */
+ public static ImageExtension fromString(final String extension) {
+ var imageExtension = STRING_TO_ENUM.get(extension);
+ if (imageExtension == null) {
+ throw new IllegalArgumentException(
+ "Invalid extension: " + extension
+ );
}
return imageExtension;
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/ImageId.java b/api/src/main/java/com/github/asavershin/api/domain/image/ImageId.java
index 690ac67..f6ef6c7 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/ImageId.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/ImageId.java
@@ -3,11 +3,26 @@
import java.util.Objects;
import java.util.UUID;
+/**
+ * A value object representing an image ID.
+ *
+ * @param value The unique identifier for the image.
+ */
public record ImageId(UUID value) {
+ /**
+ * Constructs an ImageId instance with the provided UUID.
+ *
+ * @param value The unique identifier for the image.
+ * @throws NullPointerException if the provided value is null.
+ */
public ImageId {
Objects.requireNonNull(value, "Image ID must not be null");
}
-
+ /**
+ * Generates a new, unique ImageId.
+ *
+ * @return A new ImageId instance with a randomly generated UUID.
+ */
public static ImageId nextIdentity() {
return new ImageId(UUID.randomUUID());
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/ImageNameWithExtension.java b/api/src/main/java/com/github/asavershin/api/domain/image/ImageNameWithExtension.java
index c3e321e..5b0f88f 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/ImageNameWithExtension.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/ImageNameWithExtension.java
@@ -6,41 +6,82 @@
import java.util.Arrays;
import java.util.Objects;
+
@Getter
@EqualsAndHashCode
-public class ImageNameWithExtension {
+public final class ImageNameWithExtension {
+ /**
+ * The maximum length of an image name.
+ */
private static final int MAX_IMAGE_NAME = 50;
+
+ /**
+ * The image name.
+ */
private final String imageName;
+
+ /**
+ * The image extension.
+ */
private final ImageExtension imageExtension;
- private ImageNameWithExtension(String imageName, ImageExtension imageExt){
- this.imageName = imageName;
- this.imageExtension = imageExt;
+ /**
+ * Constructs an {@code ImageNameWithExtension} object.
+ *
+ * @param aImageName the image name without last extension
+ * @param aImageExt the image extension
+ */
+ private ImageNameWithExtension(final String aImageName,
+ final ImageExtension aImageExt) {
+ this.imageName = aImageName;
+ this.imageExtension = aImageExt;
}
-
- public static ImageNameWithExtension fromOriginalFileName(String originalFileName){
+ /**
+ * Creates an {@code ImageNameWithExtension}
+ * object from an original file name.
+ *
+ * @param originalFileName the original file name
+ * @return the created {@code ImageNameWithExtension} object
+ */
+ public static ImageNameWithExtension fromOriginalFileName(
+ final String originalFileName
+ ) {
notNullValidate(originalFileName);
String[] parts = originalFileName.split("\\.");
Validator.assertArrayLength(parts, 2, "Incorrect image format");
- var extension = ImageExtension.fromString("." + parts[parts.length-1]);
- var imageName = String.join(".", Arrays.copyOfRange(parts, 0, parts.length - 1));
+ var extension = ImageExtension
+ .fromString("." + parts[parts.length - 1]);
+ var imageName = String
+ .join(".", Arrays.copyOfRange(parts, 0, parts.length - 1));
lengthNameValidate(imageName);
return new ImageNameWithExtension(imageName, extension);
}
- public static ImageNameWithExtension founded(String imageName, String extension) {
+
+ /**
+ * Creates an {@code ImageNameWithExtension}
+ * object that founded in repository from an image name and an extension.
+ *
+ * @param imageName the image name
+ * @param extension the image extension
+ * @return the created {@code ImageNameWithExtension} object
+ */
+ public static ImageNameWithExtension founded(
+ final String imageName,
+ final String extension) {
notNullValidate(imageName);
lengthNameValidate(imageName);
- return new ImageNameWithExtension(imageName, ImageExtension.fromString(extension));
+ return new ImageNameWithExtension(imageName,
+ ImageExtension.fromString(extension));
}
- private static void notNullValidate(String name){
+ private static void notNullValidate(final String name) {
Objects.requireNonNull(name, "ImageName must not be null");
}
- private static void lengthNameValidate(String name){
- Validator.assertArgumentLength(name,0, MAX_IMAGE_NAME,
+ private static void lengthNameValidate(final String name) {
+ Validator.assertArgumentLength(name, 0, MAX_IMAGE_NAME,
"ImageName must be " + 0 + "-" + MAX_IMAGE_NAME + " in length");
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/ImageRepository.java b/api/src/main/java/com/github/asavershin/api/domain/image/ImageRepository.java
index 6669ca9..5998b6b 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/ImageRepository.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/ImageRepository.java
@@ -6,10 +6,35 @@
import java.util.List;
public interface ImageRepository {
+ /**
+ * Saves an Image object to the database.
+ *
+ * @param image the Image object to be saved
+ */
void save(Image image);
- List findImagesByUserId(UserId userId, PartOfResources partOfResources);
+ /**
+ * Finds all Images associated with the given UserId and PartOfResources.
+ *
+ * @param userId the UserId of the user whose images are to be retrieved
+ * @param partOfResources the PartOfResources to filter the images by
+ * @return a list of Images associated with the given UserId
+ * and PartOfResources
+ */
+ List findImagesByUserId(UserId userId,
+ PartOfResources partOfResources);
+ /**
+ * Finds an Image by its ImageId.
+ *
+ * @param imageId the ImageId of the Image to be retrieved
+ * @return the Image object with the given ImageId, or null if not found
+ */
Image findImageByImageId(ImageId imageId);
- void deleteImageByImageId(Image ImageId);
+ /**
+ * Deletes an Image by its ImageId.
+ *
+ * @param imageId the ImageId of the Image to be deleted
+ */
+ void deleteImageByImageId(Image imageId);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/MetaData.java b/api/src/main/java/com/github/asavershin/api/domain/image/MetaData.java
new file mode 100644
index 0000000..1a34051
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/MetaData.java
@@ -0,0 +1,43 @@
+package com.github.asavershin.api.domain.image;
+
+import com.github.asavershin.api.common.Validator;
+
+import java.util.Objects;
+
+public record MetaData(ImageNameWithExtension imageNameWithExtension,
+ Long imageSize) {
+ /**
+ * The maximum length of an image name.
+ */
+ private static final int MAX_IMAGE_NAME = 50;
+ /**
+ * Size is in bytes. 10MB
+ */
+ private static final long MAX_IMAGE_SIZE = 10485760;
+
+ /**
+ * Constructs a new instance of MetaInfo
+ * and validates the provided image name and size.
+ */
+ public MetaData {
+ validateImageName(imageNameWithExtension);
+ validateImageSize(imageSize);
+ }
+
+ private void validateImageName(
+ final ImageNameWithExtension aImageNameWithExtension
+ ) {
+ Objects.requireNonNull(aImageNameWithExtension,
+ "Name and extension must not be null");
+ Validator.assertArgumentLength(aImageNameWithExtension.toString(),
+ 0, MAX_IMAGE_NAME,
+ "Image name must be "
+ + "0-" + MAX_IMAGE_NAME + " in length");
+ }
+
+ private void validateImageSize(final Long aImageSize) {
+ Objects.requireNonNull(aImageSize, "Image size must not be null");
+ Validator.assertLongSize(aImageSize, 0L, MAX_IMAGE_SIZE,
+ "Image size must be " + "0-" + MAX_IMAGE_SIZE);
+ }
+}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/MetaInfo.java b/api/src/main/java/com/github/asavershin/api/domain/image/MetaInfo.java
deleted file mode 100644
index 3fc7fd3..0000000
--- a/api/src/main/java/com/github/asavershin/api/domain/image/MetaInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.github.asavershin.api.domain.image;
-
-import com.github.asavershin.api.common.Validator;
-
-import java.util.Objects;
-
-public record MetaInfo(ImageNameWithExtension imageNameWithExtension, Long imageSize) {
- private static final int MAX_IMAGE_NAME = 50;
- /**
- * @param imageName
- * Size is in bytes. 10MB
- */
- private static final long MAX_IMAGE_SIZE = 10485760;
-
- public MetaInfo {
- validateImageName(imageNameWithExtension);
- validateImageSize(imageSize);
- }
-
- private void validateImageName(ImageNameWithExtension imageNameWithExtension) {
- Objects.requireNonNull(imageNameWithExtension, "Name and extension must not be null");
- }
-
- private void validateImageSize(Long imageSize){
- Objects.requireNonNull(imageSize, "Image size must not be null");
- Validator.assertLongSize(imageSize, 0L, MAX_IMAGE_SIZE,
- "Image size must be " + "0-" + MAX_IMAGE_SIZE + " in length");
- }
-}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/StoreImageOfUser.java b/api/src/main/java/com/github/asavershin/api/domain/image/StoreImageOfUser.java
index e292586..ab0d3d4 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/StoreImageOfUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/StoreImageOfUser.java
@@ -2,5 +2,10 @@
@FunctionalInterface
public interface StoreImageOfUser {
+ /**
+ * Stores the provided image of a user.
+ *
+ * @param image The image to be stored.
+ */
void storeImageOfUser(Image image);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/impl/DeleteImageOfUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/image/impl/DeleteImageOfUserImpl.java
index fffc7e8..569b793 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/impl/DeleteImageOfUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/impl/DeleteImageOfUserImpl.java
@@ -10,13 +10,26 @@
@Command
@RequiredArgsConstructor
-public class DeleteImageOfUserImpl extends IsEntityFound implements DeleteImageOfUser {
+public class DeleteImageOfUserImpl extends IsEntityFound
+ implements DeleteImageOfUser {
+ /**
+ * The ImageRepository dependency for accessing image data.
+ */
private final ImageRepository imageRepository;
+
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void removeImageOfUser(ImageId imageId, UserId userId) {
+ public void removeImageOfUser(
+ final ImageId imageId,
+ final UserId userId
+ ) {
var image = imageRepository.findImageByImageId(imageId);
isEntityFound(image, "Image", "Id", imageId.value().toString());
image.belongsToUser(userId);
- imageRepository.deleteImageByImageId(imageRepository.findImageByImageId(imageId));
+ imageRepository.deleteImageByImageId(
+ imageRepository.findImageByImageId(imageId)
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetImageOfUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetImageOfUserImpl.java
index 23b8074..674e5ac 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetImageOfUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetImageOfUserImpl.java
@@ -11,12 +11,25 @@
@DomainService
@RequiredArgsConstructor
-public class GetImageOfUserImpl extends IsEntityFound implements GetImageOfUser {
+public class GetImageOfUserImpl extends IsEntityFound
+ implements GetImageOfUser {
+ /**
+ * The ImageRepository dependency for accessing image data.
+ */
private final ImageRepository imageRepository;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public Image getImageOfUser(UserId userId, ImageId imageId) {
+ public Image getImageOfUser(final UserId userId,
+ final ImageId imageId) {
var image = imageRepository.findImageByImageId(imageId);
- isEntityFound(image, "Image", "Id", imageId.value().toString());
+ isEntityFound(
+ image,
+ "Image",
+ "Id",
+ imageId.value().toString()
+ );
image.belongsToUser(userId);
return image;
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetPartImagesOfUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetPartImagesOfUserImpl.java
index 34de1c8..9a85c58 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetPartImagesOfUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/impl/GetPartImagesOfUserImpl.java
@@ -13,9 +13,16 @@
@Query
@RequiredArgsConstructor
public class GetPartImagesOfUserImpl implements GetPartImagesOfUser {
+ /**
+ * The ImageRepository dependency for accessing image data.
+ */
private final ImageRepository imageRepository;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public List get(UserId userId, PartOfResources partOfResources) {
+ public List get(final UserId userId,
+ final PartOfResources partOfResources) {
return imageRepository.findImagesByUserId(userId, partOfResources);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/impl/StoreImageOfUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/image/impl/StoreImageOfUserImpl.java
index 6712b25..d48c082 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/image/impl/StoreImageOfUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/impl/StoreImageOfUserImpl.java
@@ -9,10 +9,15 @@
@Command
@RequiredArgsConstructor
public class StoreImageOfUserImpl implements StoreImageOfUser {
+ /**
+ * The ImageRepository dependency for accessing image data.
+ */
private final ImageRepository imageRepository;
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void storeImageOfUser(Image image) {
+ public void storeImageOfUser(final Image image) {
imageRepository.save(image);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/impl/package-info.java b/api/src/main/java/com/github/asavershin/api/domain/image/impl/package-info.java
new file mode 100644
index 0000000..65e29ee
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/impl/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * This package contains implementations of domain services,
+ * queries, commands for image entity.
+ *
+ * @author asavershin
+ */
+package com.github.asavershin.api.domain.image.impl;
diff --git a/api/src/main/java/com/github/asavershin/api/domain/image/package-info.java b/api/src/main/java/com/github/asavershin/api/domain/image/package-info.java
new file mode 100644
index 0000000..3e4dfaa
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/image/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains the domain model classes related to image processing.
+ * @author asavershin
+ */
+package com.github.asavershin.api.domain.image;
diff --git a/api/src/main/java/com/github/asavershin/api/domain/package-info.java b/api/src/main/java/com/github/asavershin/api/domain/package-info.java
new file mode 100644
index 0000000..9ee4b6d
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/package-info.java
@@ -0,0 +1,8 @@
+/**
+ * This package contains the entities, value objects
+ * entity repositories, queries, commands and domain
+ * services used in the application.
+ *
+ * @author Asavershin
+ */
+package com.github.asavershin.api.domain;
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/AuthException.java b/api/src/main/java/com/github/asavershin/api/domain/user/AuthException.java
index 4203fe8..e6f8635 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/AuthException.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/AuthException.java
@@ -1,7 +1,21 @@
package com.github.asavershin.api.domain.user;
+/**
+ * Represents an exception that occurs during authentication process.
+ *
+ * @author asavershin
+ */
public class AuthException extends RuntimeException {
- public AuthException(String message){
+
+ /**
+ * Constructs an instance of AuthException with
+ * the specified detail message.
+ *
+ * @param message the detail message.
+ * The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public AuthException(final String message) {
super(message);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUser.java b/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUser.java
index e6c4184..28bfc2e 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUser.java
@@ -1,6 +1,5 @@
package com.github.asavershin.api.domain.user;
-import com.github.asavershin.api.domain.IsEntityFound;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -10,26 +9,51 @@
@Getter
@ToString
@EqualsAndHashCode
-public class AuthenticatedUser {
+public final class AuthenticatedUser {
+ /**
+ * The unique identifier of the user.
+ */
private UserId userId;
+
+ /**
+ * The credentials of the user.
+ */
private Credentials userCredentials;
- private AuthenticatedUser(UserId userId, Credentials userCredentials) {
- setUserId(userId);
- setUserCredentials(userCredentials);
+ /**
+ * Constructs an instance of AuthenticatedUser
+ * with the provided userId and userCredentials.
+ *
+ * @param aUserId the unique identifier of the user
+ * @param aUserCredentials the credentials of the user
+ */
+ private AuthenticatedUser(final UserId aUserId,
+ final Credentials aUserCredentials) {
+ setUserId(aUserId);
+ setUserCredentials(aUserCredentials);
}
- public static AuthenticatedUser founded(UserId userId, Credentials credentials) {
+ /**
+ * Creates a new instance of AuthenticatedUser that becomes from repository
+ * with the provided userId and userCredentials.
+ *
+ * @param userId the unique identifier of the user
+ * @param credentials the credentials of the user
+ * @return a new instance of AuthenticatedUser
+ */
+ public static AuthenticatedUser founded(final UserId userId,
+ final Credentials credentials) {
return new AuthenticatedUser(userId, credentials);
}
- private void setUserId(UserId userId) {
- Objects.requireNonNull(userId, "UserId must not be null");
- this.userId = userId;
+ private void setUserId(final UserId aUserId) {
+ Objects.requireNonNull(aUserId, "UserId must not be null");
+ this.userId = aUserId;
}
- private void setUserCredentials(Credentials userCredentials) {
- Objects.requireNonNull(userCredentials, "UserCredentials must not be null");
- this.userCredentials = userCredentials;
+ private void setUserCredentials(final Credentials aUserCredentials) {
+ Objects.requireNonNull(aUserCredentials,
+ "UserCredentials must not be null");
+ this.userCredentials = aUserCredentials;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUserRepository.java b/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUserRepository.java
index 037c05e..5ac94d9 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUserRepository.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/AuthenticatedUserRepository.java
@@ -1,7 +1,14 @@
package com.github.asavershin.api.domain.user;
-import java.util.Optional;
-
+/**
+ * Represents a repository for finding authenticated users by their email.
+ */
public interface AuthenticatedUserRepository {
+ /**
+ * Finds an authenticated user by their email.
+ *
+ * @param email the email of the user to find
+ * @return the authenticated user with the given email, or null if not found
+ */
AuthenticatedUser findByEmail(String email);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/Credentials.java b/api/src/main/java/com/github/asavershin/api/domain/user/Credentials.java
index e593614..96a59e4 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/Credentials.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/Credentials.java
@@ -6,28 +6,48 @@
import java.util.Objects;
public record Credentials(String email, String password) {
+ /**
+ * The maximum length of an email.
+ */
private static final int MAX_EMAIL_LENGTH = 50;
+
+ /**
+ * The minimum length of an email.
+ */
private static final int MIN_EMAIL_LENGTH = 5;
+
+ /**
+ * The minimum length of a password.
+ */
private static final int MIN_PASSWORD_LENGTH = 8;
+ /**
+ * Constructs a new instance of Credentials.
+ * Validates the email and password before creating the instance.
+ */
public Credentials {
validateEmail(email);
validatePassword(password);
}
- private void validateEmail(String email) {
- Objects.requireNonNull(email, "Email must not be null");
- Validator.assertArgumentLength(email,
+ private void validateEmail(final String aEmail) {
+ Objects.requireNonNull(aEmail, "Email must not be null");
+ Validator.assertArgumentLength(aEmail,
MIN_EMAIL_LENGTH, MAX_EMAIL_LENGTH,
- "Email must be " + MIN_EMAIL_LENGTH + "-" + MAX_EMAIL_LENGTH + " in length");
+ "Email must be "
+ + MIN_EMAIL_LENGTH + "-"
+ + MAX_EMAIL_LENGTH + " in length");
- Validator.assertStringFormat(email, "[A-Za-z0-9_.+-]+@[A-Za-z0-9-]+\\.[A-Za-z0-9.-]+",
+ Validator.assertStringFormat(aEmail,
+ "[A-Za-z0-9_.+-]+@[A-Za-z0-9-]+\\.[A-Za-z0-9.-]+",
"Email is not in the correct format");
}
- private void validatePassword(String password) {
- Objects.requireNonNull(password, "Password must not be null");
- Validator.assertArgumentLength(password, MIN_PASSWORD_LENGTH, "Password must be greater than " + MIN_PASSWORD_LENGTH);
+ private void validatePassword(final String aPassword) {
+ Objects.requireNonNull(aPassword, "Password must not be null");
+ Validator.assertArgumentLength(aPassword,
+ MIN_PASSWORD_LENGTH,
+ "Password must be greater than " + MIN_PASSWORD_LENGTH);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/FullName.java b/api/src/main/java/com/github/asavershin/api/domain/user/FullName.java
index 1190c92..162a715 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/FullName.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/FullName.java
@@ -1,23 +1,45 @@
package com.github.asavershin.api.domain.user;
-
import com.github.asavershin.api.common.Validator;
import java.util.Objects;
+/**
+ * A value object representing a user's full name,
+ * consisting of a first name and a last name.
+ * The length of each name is limited to 20 characters.
+ *
+ * @param firstname The first name of the user
+ * @param lastname The last name of the user
+ */
public record FullName(String firstname, String lastname) {
+ /**
+ * The maximum length of a first name.
+ */
private static final int MAX_FIRST_NAME_LENGTH = 20;
+ /**
+ * The maximum length of a last name.
+ */
private static final int MAX_LAST_NAME_LENGTH = 20;
+ /**
+ * Constructs a new instance of FullName and validates the length of
+ * the first and last names.
+ */
public FullName {
validateName(firstname, MAX_FIRST_NAME_LENGTH);
validateName(lastname, MAX_LAST_NAME_LENGTH);
}
- private void validateName(String name, int maxLength) {
+ private void validateName(final String name, final int maxLength) {
Objects.requireNonNull(name, "Firstname must not be null");
- Validator.assertArgumentLength(name, 0, MAX_FIRST_NAME_LENGTH, "Name must be " + "0-" + maxLength + " in length");
+ Validator.assertArgumentLength(
+ name,
+ 0,
+ MAX_FIRST_NAME_LENGTH,
+ "Name must be " + "0-" + maxLength + " in length"
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/GetPartOfImagesForAuthenticatedUser.java b/api/src/main/java/com/github/asavershin/api/domain/user/GetPartOfImagesForAuthenticatedUser.java
index 946eefa..a4ede32 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/GetPartOfImagesForAuthenticatedUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/GetPartOfImagesForAuthenticatedUser.java
@@ -5,7 +5,22 @@
import java.util.List;
+/**
+ * This interface represents a function that retrieves a list of images
+ * for a given authenticated user and a specific part of resources.
+ *
+ */
@FunctionalInterface
public interface GetPartOfImagesForAuthenticatedUser {
- public List get(UserId userId, PartOfResources partOfResources);
+ /**
+ * Retrieves a list of images for a given authenticated user and
+ * a specific part of resources.
+ *
+ * @param userId the unique identifier of the authenticated user
+ * @param partOfResources the specific part of resources
+ * for which the images are requested
+ * @return a list of images associated with the specified
+ * user and part of resources
+ */
+ List get(UserId userId, PartOfResources partOfResources);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/RegisterNewUser.java b/api/src/main/java/com/github/asavershin/api/domain/user/RegisterNewUser.java
index a3caf54..a3a4b5f 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/RegisterNewUser.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/RegisterNewUser.java
@@ -1,6 +1,18 @@
package com.github.asavershin.api.domain.user;
+/**
+ * A functional interface that represents a method to register a new user.
+ *
+ */
@FunctionalInterface
public interface RegisterNewUser {
+ /**
+ * Registers a new user with the provided full name and credentials.
+ *
+ * @param fullName The FullName value object
+ * containing the user's full name.
+ * @param credentials The Credentials value object
+ * containing the user's credentials.
+ */
void register(FullName fullName, Credentials credentials);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/TryToLogin.java b/api/src/main/java/com/github/asavershin/api/domain/user/TryToLogin.java
index a6a17f8..374164d 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/TryToLogin.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/TryToLogin.java
@@ -1,6 +1,20 @@
package com.github.asavershin.api.domain.user;
+/**
+ * A functional interface representing a login operation for user
+ * using login, password.
+ *
+ * @author asavershin
+ * @since 1.0
+ */
@FunctionalInterface
public interface TryToLogin {
+ /**
+ * Attempts to log the user in using the provided credentials.
+ *
+ * @param credentials The credentials to use for login.
+ * @return An instance of {@link AuthenticatedUser}
+ * if the login is successful, otherwise null.
+ */
AuthenticatedUser login(Credentials credentials);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/User.java b/api/src/main/java/com/github/asavershin/api/domain/user/User.java
index 061f25a..d1b2133 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/User.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/User.java
@@ -1,3 +1,9 @@
+/**
+ * User class represents a user entity in the system.
+ * It contains the user's unique identifier, full name, and credentials.
+ *
+ * @author asavershin
+ */
package com.github.asavershin.api.domain.user;
import lombok.EqualsAndHashCode;
@@ -8,32 +14,53 @@
@ToString
@EqualsAndHashCode
-public class User{
- @Getter
+@Getter
+public class User {
+ /**
+ * The unique identifier for the user.
+ */
private UserId userId;
- @Getter
+
+ /**
+ * The full name of the user.
+ */
private FullName userFullName;
- @Getter
+
+ /**
+ * The credentials of the user.
+ */
private Credentials userCredentials;
- public User(UserId userId, FullName userFullName, Credentials userCredentials) {
- setUserId(userId);
- setUserCredentials(userCredentials);
- setUserFullName(userFullName);
+ /**
+ * Constructor for User class.
+ *
+ * @param id the unique identifier for the user
+ * @param fullname the full name of the user
+ * @param credentials the credentials of the user
+ */
+ public User(final UserId id,
+ final FullName fullname,
+ final Credentials credentials) {
+ setUserId(id);
+ setUserCredentials(credentials);
+ setUserFullName(fullname);
}
- private void setUserId(UserId userId) {
- Objects.requireNonNull(userId, "UserId must not be null");
- this.userId = userId;
+ private void setUserId(final UserId id) {
+ Objects.requireNonNull(id,
+ "UserId must not be null");
+ this.userId = id;
}
- private void setUserFullName(FullName userFullName) {
- Objects.requireNonNull(userFullName, "UserFullName must not be null");
- this.userFullName = userFullName;
+ private void setUserFullName(final FullName fullName) {
+ Objects.requireNonNull(fullName,
+ "UserFullName must not be null");
+ this.userFullName = fullName;
}
- private void setUserCredentials(Credentials userCredentials) {
- Objects.requireNonNull(userCredentials, "UserCredentials must not be null");
- this.userCredentials = userCredentials;
+ private void setUserCredentials(final Credentials credentials) {
+ Objects.requireNonNull(credentials,
+ "UserCredentials must not be null");
+ this.userCredentials = credentials;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/UserId.java b/api/src/main/java/com/github/asavershin/api/domain/user/UserId.java
index 1f672dd..c463fcf 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/UserId.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/UserId.java
@@ -1,15 +1,36 @@
+/**
+ * A unique identifier for a user.
+ *
+ * @author asavershin
+ */
package com.github.asavershin.api.domain.user;
-import lombok.EqualsAndHashCode;
-
import java.util.Objects;
import java.util.UUID;
+/**
+ * A value object representing a unique identifier for a user.
+ *
+ * @param value The unique identifier for the user.
+ */
public record UserId(UUID value) {
+
+ /**
+ * Constructs a new instance of {@code UserId} with the provided
+ * unique identifier.
+ *
+ * @param value The unique identifier for the user.
+ * @throws NullPointerException if the provided value is null.
+ */
public UserId {
Objects.requireNonNull(value, "User ID must not be null");
}
+ /**
+ * Generates a new unique identifier for a user.
+ *
+ * @return A new unique identifier for a user.
+ */
public static UserId nextIdentity() {
return new UserId(UUID.randomUUID());
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/UserRepository.java b/api/src/main/java/com/github/asavershin/api/domain/user/UserRepository.java
index df27a0c..e21f666 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/UserRepository.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/UserRepository.java
@@ -1,9 +1,27 @@
package com.github.asavershin.api.domain.user;
-import java.util.Optional;
-
+/**
+ * UserRepository interface provides methods to interact with the User
+ * data.
+ *
+ * @author Tabnine
+ */
public interface UserRepository {
+
+ /**
+ * Saves a new User object to the repository.
+ *
+ * @param newUser the User object to be saved
+ */
void save(User newUser);
+ /**
+ * Checks if a User with the given email already exists in the
+ * repository.
+ *
+ * @param email the email of the User to be checked
+ * @return true if a User with the given email already exists,
+ * false otherwise
+ */
boolean existByUserEmail(String email);
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/impl/GetPartOfImagesForAuthenticatedUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/user/impl/GetPartOfImagesForAuthenticatedUserImpl.java
index bf6a572..d3eb2e8 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/impl/GetPartOfImagesForAuthenticatedUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/impl/GetPartOfImagesForAuthenticatedUserImpl.java
@@ -10,12 +10,28 @@
import java.util.List;
+/**
+ * Implementation of the {@link GetPartOfImagesForAuthenticatedUser} interface.
+ * This class provides methods to retrieve a part of
+ * images for an authenticated user.
+ *
+ * @author asavershin
+ */
@Query
@RequiredArgsConstructor
-public class GetPartOfImagesForAuthenticatedUserImpl implements GetPartOfImagesForAuthenticatedUser {
+public class GetPartOfImagesForAuthenticatedUserImpl
+ implements GetPartOfImagesForAuthenticatedUser {
+ /**
+ * The ImageRepository dependency for fetching images.
+ */
private final ImageRepository imageRepository;
+
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public List get(UserId userId, PartOfResources partOfResources) {
+ public List get(final UserId userId,
+ final PartOfResources partOfResources) {
return imageRepository.findImagesByUserId(userId, partOfResources);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/impl/RegisterNewUserImpl.java b/api/src/main/java/com/github/asavershin/api/domain/user/impl/RegisterNewUserImpl.java
index 4a2984b..82fe96f 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/impl/RegisterNewUserImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/impl/RegisterNewUserImpl.java
@@ -1,38 +1,53 @@
package com.github.asavershin.api.domain.user.impl;
import com.github.asavershin.api.common.annotations.Command;
+import com.github.asavershin.api.domain.user.Credentials;
+import com.github.asavershin.api.domain.user.FullName;
+import com.github.asavershin.api.domain.user.RegisterNewUser;
+import com.github.asavershin.api.domain.user.User;
+import com.github.asavershin.api.domain.user.UserId;
+import com.github.asavershin.api.domain.user.UserRepository;
import org.springframework.security.crypto.password.PasswordEncoder;
-import com.github.asavershin.api.domain.user.*;
-import com.github.asavershin.api.domain.user.RegisterNewUser;
import lombok.RequiredArgsConstructor;
@Command
@RequiredArgsConstructor
public class RegisterNewUserImpl implements RegisterNewUser {
+ /**
+ * Dependency that allow crud with User entity.
+ */
private final UserRepository userRepository;
+ /**
+ * is used to encode and decode passwords securely.
+ */
private final PasswordEncoder passwordEncoder;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void register(FullName fullName, Credentials credentials) {
+ public void register(final FullName fullName,
+ final Credentials credentials) {
checkEmailForUnique(credentials.email());
userRepository.save(
new User(
UserId.nextIdentity(),
fullName,
- new Credentials(credentials.email(), protectPassword(credentials.password()))
+ new Credentials(credentials.email(),
+ protectPassword(credentials.password()))
)
);
}
- private void checkEmailForUnique(String email) {
+ private void checkEmailForUnique(final String email) {
if (userRepository.existByUserEmail(email)) {
throw new IllegalArgumentException("Email is not unique");
}
}
- private String protectPassword(String unprotectedPassword) {
+ private String protectPassword(final String unprotectedPassword) {
return passwordEncoder.encode(unprotectedPassword);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/impl/TryToLoginImpl.java b/api/src/main/java/com/github/asavershin/api/domain/user/impl/TryToLoginImpl.java
index be33cb2..3823a7d 100644
--- a/api/src/main/java/com/github/asavershin/api/domain/user/impl/TryToLoginImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/impl/TryToLoginImpl.java
@@ -13,17 +13,28 @@
@DomainService
@RequiredArgsConstructor
public class TryToLoginImpl extends IsEntityFound implements TryToLogin {
-
+ /**
+ * The {@link PasswordEncoder}
+ * is used to encode and decode passwords securely.
+ */
private final PasswordEncoder passwordEncoder;
+ /**
+ * The {@link AuthenticatedUserRepository} is used
+ * to retrieve user data from the database.
+ */
private final AuthenticatedUserRepository authenticatedUserRepository;
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public AuthenticatedUser login(Credentials credentials) {
+ public AuthenticatedUser login(final Credentials credentials) {
- var authenticatedUser = authenticatedUserRepository.findByEmail(credentials.email());
+ var authenticatedUser = authenticatedUserRepository
+ .findByEmail(credentials.email());
- isEntityFound(authenticatedUser,"User", "email", credentials.email());
- if(passwordEncoder.matches(credentials.password(), authenticatedUser.userCredentials().password())) {
+ isEntityFound(authenticatedUser, "User", "email", credentials.email());
+ if (passwordEncoder.matches(credentials.password(),
+ authenticatedUser.userCredentials().password())) {
return authenticatedUser;
}
throw new AuthException("Wrong password");
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/impl/package-info.java b/api/src/main/java/com/github/asavershin/api/domain/user/impl/package-info.java
new file mode 100644
index 0000000..a591eda
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/impl/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * This package contains implementations of domain services,
+ * queries, commands for user entity.
+ *
+ * @author asavershin
+ */
+package com.github.asavershin.api.domain.user.impl;
diff --git a/api/src/main/java/com/github/asavershin/api/domain/user/package-info.java b/api/src/main/java/com/github/asavershin/api/domain/user/package-info.java
new file mode 100644
index 0000000..859ec6c
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/domain/user/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * This package contains the domain model for the user entity.
+ *
+ * @author asavershin
+ */
+package com.github.asavershin.api.domain.user;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AdviceController.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AdviceController.java
index 8b4fa5b..eb5e5e7 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AdviceController.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AdviceController.java
@@ -7,69 +7,117 @@
import com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.UISuccessContainer;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@RestControllerAdvice
-@Slf4j
public class AdviceController {
-
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler({ResourceOwnershipException.class, AuthException.class})
@ResponseStatus(HttpStatus.UNAUTHORIZED)
- public UISuccessContainer handleValidationException(RuntimeException ex) {
+ public UISuccessContainer handleValidationException(
+ final RuntimeException ex
+ ) {
return new UISuccessContainer(false, ex.getMessage());
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler({NotFoundException.class})
@ResponseStatus(HttpStatus.NO_CONTENT)
- public UISuccessContainer handleNotFoundException(RuntimeException ex) {
+ public UISuccessContainer handleNotFoundException(
+ final RuntimeException ex
+ ) {
return new UISuccessContainer(false, ex.getMessage());
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler({Exception.class})
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
- public UISuccessContainer handleInnerException(Exception ex) {
+ public UISuccessContainer handleInnerException(final Exception ex) {
+ ex.printStackTrace();
return new UISuccessContainer(false, "Very bad exception");
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler({IllegalArgumentException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
- public UISuccessContainer handleIllegalImageExtension(IllegalArgumentException ex) {
- log.info("IllegaArgumentException: " + ex);
+ public UISuccessContainer handleIllegalImageExtension(
+ final IllegalArgumentException ex
+ ) {
return new UISuccessContainer(false, ex.getMessage());
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
- public ExceptionBody handleValidationException(MethodArgumentNotValidException ex) {
- log.info("handleValidationException");
+ public ExceptionBody handleValidationException(
+ final MethodArgumentNotValidException ex
+ ) {
var exceptionBody = new ExceptionBody("Validation failed: ");
Map body = new HashMap<>();
body.put("errors",
ex.getBindingResult().getAllErrors().stream()
- .map(DefaultMessageSourceResolvable::getDefaultMessage).filter(Objects::nonNull)
+ .map(
+ DefaultMessageSourceResolvable
+ ::getDefaultMessage
+ )
+ .filter(Objects::nonNull)
.toList());
exceptionBody.setErrors(body);
return exceptionBody;
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param ex is handled exception
+ * @return Exception representation for user.
+ */
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
- public ExceptionBody handleConstraintViolationException(ConstraintViolationException ex) {
- log.info("handleConstraintViolationException");
+ public ExceptionBody handleConstraintViolationException(
+ final ConstraintViolationException ex
+ ) {
var exceptionBody = new ExceptionBody("Validation failed: ");
Map body = new HashMap<>();
body.put("errors",
ex.getConstraintViolations().stream()
- .map(ConstraintViolation::getMessage).filter(Objects::nonNull)
+ .map(ConstraintViolation::getMessage)
+ .filter(Objects::nonNull)
.toList());
exceptionBody.setErrors(body);
return exceptionBody;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AuthController.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AuthController.java
index 35c3cf6..e654795 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AuthController.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/AuthController.java
@@ -11,7 +11,6 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -23,30 +22,56 @@
@Tag(name = "auth", description = "Аутентификация и регистрация")
@RequiredArgsConstructor
public class AuthController {
-
+ /**
+ * Dependency that allows to register new user.
+ */
private final RegisterNewUser register;
+ /**
+ * Dependency that allows to get new tokens during authentication.
+ */
private final GetNewCredentials getNewCredentials;
- private final GetNewCredentialsUsingRefreshToken getNewCredentialsUsingRefreshToken;
+ /**
+ * Dependency that allows to get new tokens using refresh token.
+ */
+ private final GetNewCredentialsUsingRefreshToken getRefreshToken;
+ /**
+ * Not final to allows Spring use proxy.
+ * @param request DTO that contains user data like email, password
+ * firstname, etc.
+ */
@PostMapping("/register")
@Operation(description = "Регистрация нового пользователя")
public void register(
- @RequestBody @Valid UserRegistrationRequest userRegistrationRequest
+ final @RequestBody @Valid UserRegistrationRequest request
) {
- register.register(userRegistrationRequest.ToFullName(),
- userRegistrationRequest.toCredentials());
+ register.register(request.toFullName(),
+ request.toCredentials());
}
+ /**
+ * Not final to allows Spring use proxy.
+ * @param userLoginRequest DTO that represents login, password.
+ * @return DTO that contains access, refresh tokens
+ */
@PostMapping("/login")
@Operation(description = "Аутентификация пользователя")
- public ApplicationCredentials login(@RequestBody @Valid UserLoginRequest userLoginRequest) {
-
+ public ApplicationCredentials login(
+ final @RequestBody @Valid UserLoginRequest userLoginRequest
+ ) {
return getNewCredentials.get(userLoginRequest.toCredentials());
}
-
+ /**
+ * Not final to allows Spring use proxy.
+ * @param user Is param that injects by spring and contains
+ * current authenticated spring user.
+ * @return DTO that contains access, refresh tokens.
+ */
@PostMapping("/refresh-token")
@Operation(description = "Использовать рефреш токен")
- public ApplicationCredentials refreshToken(@AuthenticationPrincipal CustomUserDetails user) {
- return getNewCredentialsUsingRefreshToken.get(user.authenticatedUser().userCredentials());
+ public ApplicationCredentials refreshToken(
+ final @AuthenticationPrincipal CustomUserDetails user
+ ) {
+ return getRefreshToken.get(user.authenticatedUser().userCredentials());
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/ImageController.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/ImageController.java
index cfc5229..88d7211 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/ImageController.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/ImageController.java
@@ -11,9 +11,14 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.UUID;
@@ -23,47 +28,99 @@
@Tag(name = "image", description = "Работа с изображениями")
@RequiredArgsConstructor
public class ImageController {
-
+ /**
+ * Domain query that allows you take images of specific user.
+ */
private final GetPartOfImagesForAuthenticatedUser getImages;
+ /**
+ * Application service that contains logic for images get, post, delete.
+ * It contains some others dependencies for databases and jwt service.
+ */
private final ImageService imageService;
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param user Is param that injects by spring and contains
+ * current authenticated spring user.
+ * @param pageNumber Page number for pagination in DB
+ * @param pageSize Page size for pagination in DB
+ * @return List of images for specific user.
+ */
@GetMapping("/images")
@Operation(description = "Получить изображения пользователя")
- public GetImagesResponse getImages(@AuthenticationPrincipal CustomUserDetails user,
- Long pageNumber,
- Long pageSize) {
- return GetImagesResponse.GetImagesResponseFromImages(
- getImages.get(user.authenticatedUser().userId(), new PartOfResources(pageNumber, pageSize))
+ public GetImagesResponse getImages(
+ final @AuthenticationPrincipal CustomUserDetails user,
+ final Long pageNumber,
+ final Long pageSize
+ ) {
+ return GetImagesResponse.getImagesResponseFromImages(
+ getImages.get(user.authenticatedUser().userId(),
+ new PartOfResources(pageNumber, pageSize)
+ )
);
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param user Is param that injects by spring and contains
+ * current authenticated spring user.
+ * @param file Is image with data and metadata.
+ * @return ImageId of the new image
+ */
@PostMapping
@Operation(description = "Загрузить новую картинку")
public UploadImageResponse uploadImage(
- @AuthenticationPrincipal CustomUserDetails user,
- @RequestPart("file") MultipartFile file
+ final @AuthenticationPrincipal CustomUserDetails user,
+ final @RequestPart("file") MultipartFile file
) {
- return new UploadImageResponse(imageService.storeImage(user.authenticatedUser().userId(), file));
+ return new UploadImageResponse(
+ imageService.storeImage(
+ user.authenticatedUser().userId(),
+ file
+ )
+ );
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param user Is param that injects by spring and contains
+ * current authenticated spring user.
+ * @param imageId The id of the image
+ * @return The response that contains status of response(true, false)
+ * and message for user about successful.
+ */
@DeleteMapping("/{image-id}")
@Operation(description = "Удалить картинку")
public UISuccessContainer deleteImage(
- @AuthenticationPrincipal CustomUserDetails user,
- @PathVariable("image-id") String imageId
+ final @AuthenticationPrincipal CustomUserDetails user,
+ final @PathVariable("image-id") String imageId
) {
- imageService.deleteImageByImageId(user.authenticatedUser().userId(), new ImageId(UUID.fromString(imageId)));
+ imageService.deleteImageByImageId(
+ user.authenticatedUser().userId(),
+ new ImageId(UUID.fromString(imageId))
+ );
return new UISuccessContainer(
true,
- "Image with id " + imageId +" deleted successfully"
+ "Image with id " + imageId + " deleted successfully"
);
}
+ /**
+ * Not final to allows Spring use proxy.
+ *
+ * @param user Is param that injects by spring and contains
+ * current authenticated spring user.
+ * @param imageId The id of the image
+ * @return bytes of the image
+ */
@GetMapping("/{image-id}")
@Operation(description = "Получить картинку по id")
public byte[] downloadImage(
- @AuthenticationPrincipal CustomUserDetails user,
- @PathVariable("image-id") String imageId
+ final @AuthenticationPrincipal CustomUserDetails user,
+ final @PathVariable("image-id") String imageId
) {
return imageService.downloadImage(
new ImageId(UUID.fromString(imageId)),
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/ExceptionBody.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/ExceptionBody.java
index 3c094b6..12b74e1 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/ExceptionBody.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/ExceptionBody.java
@@ -10,14 +10,24 @@
@Setter
@AllArgsConstructor
public class ExceptionBody {
-
+ /**
+ * Message for user about exception.
+ */
private String message;
+ /**
+ * Map of error for a lot of exceptions.
+ */
private Map errors;
-
+ /**
+ * Constructs an instance of {@link ExceptionBody}
+ * with the provided message.
+ *
+ * @param aMessage Message for user about exception.
+ */
public ExceptionBody(
- final String message
+ final String aMessage
) {
- this.message = message;
+ this.message = aMessage;
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/UISuccessContainer.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/UISuccessContainer.java
index f7ab7b7..c80f9a8 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/UISuccessContainer.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/UISuccessContainer.java
@@ -6,6 +6,12 @@
@Getter
@AllArgsConstructor
public class UISuccessContainer {
+ /**
+ * Indicates whether the operation was successful.
+ */
private boolean success;
+ /**
+ * The message to be displayed to the user.
+ */
private String message;
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/GetImagesResponse.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/GetImagesResponse.java
index 2b7d65a..7792a11 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/GetImagesResponse.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/GetImagesResponse.java
@@ -1,22 +1,33 @@
package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.image;
import com.github.asavershin.api.domain.image.Image;
-import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
-import java.util.stream.Collectors;
@Getter
-public class GetImagesResponse {
- private List images;
- private GetImagesResponse(List images){
- this.images = images;
+public final class GetImagesResponse {
+ /**
+ * List of metadata of images.
+ */
+ private final List images;
+
+ private GetImagesResponse(final List aImages) {
+ this.images = aImages;
}
- public static GetImagesResponse GetImagesResponseFromImages(List images) {
+
+ /**
+ * Static fabric that map List of images to list of DTO.
+ *
+ * @param images List of images from domain
+ * @return Instance of GetImagesResponse
+ */
+ public static GetImagesResponse getImagesResponseFromImages(
+ final List images
+ ) {
return new GetImagesResponse(
images.stream()
- .map(ImageResponse::imageResponseFromEntity).toList()
+ .map(ImageResponse::imageResponseFromEntity).toList()
);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/ImageResponse.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/ImageResponse.java
index 7b2a6a8..9600724 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/ImageResponse.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/ImageResponse.java
@@ -4,18 +4,35 @@
import lombok.Getter;
@Getter
-public class ImageResponse {
- private String ImageId;
- private String ImageName;
- private Long imageSize;
+public final class ImageResponse {
+ /**
+ * UUID of the image.
+ */
+ private final String imageId;
+ /**
+ * Image name in format "name.extension".
+ */
+ private final String imageName;
+ /**
+ * Count of image bytes.
+ */
+ private final Long imageSize;
- private ImageResponse(String ImageId, String ImageName, Long imageSize){
- this.ImageId = ImageId;
- this.ImageName = ImageName;
- this.imageSize = imageSize;
+ private ImageResponse(final String aImageId,
+ final String aImageName,
+ final Long aImageSize) {
+ this.imageId = aImageId;
+ this.imageName = aImageName;
+ this.imageSize = aImageSize;
}
- public static ImageResponse imageResponseFromEntity(Image image){
+ /**
+ * Static fabric for creating ImageResponse from image entity.
+ *
+ * @param image is domain entity
+ * @return DTO
+ */
+ public static ImageResponse imageResponseFromEntity(final Image image) {
return new ImageResponse(
image.imageId().value().toString(),
image.metaInfo().imageNameWithExtension().toString(),
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/UploadImageResponse.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/UploadImageResponse.java
index 165a742..3e05d1a 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/UploadImageResponse.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/UploadImageResponse.java
@@ -1,13 +1,18 @@
package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.image;
import com.github.asavershin.api.domain.image.ImageId;
-import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
public class UploadImageResponse {
- private String imageId;
- public UploadImageResponse(ImageId imageId){
- this.imageId = imageId.value().toString();
+ /**
+ * UUID of the image.
+ */
+ private final String imageId;
+ /**
+ * @param aImageId UUID of the image
+ */
+ public UploadImageResponse(final ImageId aImageId) {
+ this.imageId = aImageId.value().toString();
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/package-info.java
new file mode 100644
index 0000000..d513554
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/image/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains image DTO's for HTTP reuqests/respons.
+ * @author asavershin
+ */
+package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.image;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/package-info.java
new file mode 100644
index 0000000..417722c
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains DTO's for HTTP reuqests/respons.
+ * @author asavershin
+ */
+package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserLoginRequest.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserLoginRequest.java
index d3ca761..03abb31 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserLoginRequest.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserLoginRequest.java
@@ -10,15 +10,30 @@
@Setter
@Getter
public class UserLoginRequest {
+ /**
+ * Minimum password length.
+ */
+ private static final int MIN_PASSWORD_LENGTH = 8;
+ /**
+ * User email using as login.
+ */
@NotEmpty(message = "Не заполнен email")
@Email(message = "Некорректная почта")
private String userEmail;
+ /**
+ * User password.
+ */
@NotEmpty(message = "Не заполнен пароль")
- @Size(min = 8, message = "Длина пароля должна быть не менее 8")
+ @Size(min = MIN_PASSWORD_LENGTH,
+ message = "Длина пароля должна быть не менее 8")
private String userPassword;
- public Credentials toCredentials() {
+ /**
+ * Fabric using for mapping DTO to credentials.
+ * @return User credentials
+ */
+ public final Credentials toCredentials() {
return new Credentials(userEmail, userPassword);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserRegistrationRequest.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserRegistrationRequest.java
index 0165581..55132c4 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserRegistrationRequest.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/UserRegistrationRequest.java
@@ -1,6 +1,7 @@
package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.user;
+import com.github.asavershin.api.config.properties.UserProperties;
import com.github.asavershin.api.domain.user.Credentials;
import com.github.asavershin.api.domain.user.FullName;
import jakarta.validation.constraints.Email;
@@ -12,28 +13,51 @@
@Setter
public class UserRegistrationRequest {
+
+ /**
+ * User firstname.
+ */
@NotEmpty(message = "Не заполнено имя")
- @Size(min = 1, max = 20, message = "Недопустимая длина имени")
+ @Size(min = 1, max = UserProperties.MAX_FIRSTNAME_LENGTH,
+ message = "Недопустимая длина имени")
private String userFirstname;
+ /**
+ * User lastname.
+ */
@NotEmpty(message = "Не заполнена фамилия")
- @Size(min = 1, max = 20, message = "Недопустимая длина фамилии")
+ @Size(min = 1, max = UserProperties.MAX_LASTNAME_LENGTH,
+ message = "Недопустимая длина фамилии")
private String userLastname;
-
+ /**
+ * User email using as login.
+ */
@NotEmpty(message = "Не заполнен email")
@Email(message = "Некорректная почта")
@Getter
private String userEmail;
+ /**
+ * User password.
+ */
@NotEmpty(message = "Не заполнен пароль")
- @Size(min = 8, message = "Длина пароля должна быть не менее 8")
+ @Size(min = UserProperties.MIN_PASSWORD_LENGTH,
+ message = "Длина пароля должна быть не менее 8")
@Getter
private String userPassword;
- public FullName ToFullName() {
+ /**
+ * Fabric method to create FullName from DTO.
+ * @return FullName value object
+ */
+ public FullName toFullName() {
return new FullName(userFirstname, userLastname);
}
+ /**
+ * Fabric method to create credentials.
+ * @return Credentials value object
+ */
public Credentials toCredentials() {
return new Credentials(userEmail, userPassword);
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/package-info.java
new file mode 100644
index 0000000..c81e2bd
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/dto/user/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains user DTO's for HTTP reuqests/respons.
+ * @author asavershin
+ */
+package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers.dto.user;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/package-info.java
new file mode 100644
index 0000000..0b178e4
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/impl/controllers/controllers/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * This package contains controllers that handle http requests.
+ */
+package com.github.asavershin.api.infrastructure.in.impl.controllers.controllers;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/CustomUserDetails.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/CustomUserDetails.java
index a14e57f..0a130ef 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/CustomUserDetails.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/CustomUserDetails.java
@@ -7,7 +7,8 @@
import java.util.Collection;
import java.util.List;
-public record CustomUserDetails(AuthenticatedUser authenticatedUser) implements UserDetails {
+public record CustomUserDetails(AuthenticatedUser authenticatedUser)
+ implements UserDetails {
@Override
public Collection extends GrantedAuthority> getAuthorities() {
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/JwtAuthenticationFilter.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/JwtAuthenticationFilter.java
index f41e747..81b6bea 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/JwtAuthenticationFilter.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/JwtAuthenticationFilter.java
@@ -2,13 +2,12 @@
import com.github.asavershin.api.application.out.TokenRepository;
import com.github.asavershin.api.application.in.services.user.JwtService;
-import com.github.asavershin.api.domain.user.Credentials;
+import com.github.asavershin.api.config.properties.JwtProperties;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -21,24 +20,37 @@
@Component
@RequiredArgsConstructor
-@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
-
+ /**
+ * JwtService dependency injection.
+ *
+ * @see com.github.asavershin.api.application.in.services.user.JwtService
+ */
private final JwtService jwtService;
+
+ /**
+ * UserDetailsService dependency injection.
+ *
+ * @see com.github.asavershin.api.application.out.TokenRepository
+ */
private final UserDetailsService userDetailsService;
+
+ /**
+ * TokenRepository dependency injection.
+ *
+ * @see com.github.asavershin.api.application.out.TokenRepository
+ */
private final TokenRepository tokenRepository;
@Override
- protected void doFilterInternal(
- @NonNull HttpServletRequest request,
- @NonNull HttpServletResponse response,
- @NonNull FilterChain filterChain
+ protected final void doFilterInternal(
+ final @NonNull HttpServletRequest request,
+ final @NonNull HttpServletResponse response,
+ final @NonNull FilterChain filterChain
) throws ServletException, IOException {
- log.info("Start JWT authentication filter");
var path = request.getServletPath();
if (path.contains("/register") || path.contains("/login")) {
- log.info("REGISTER OR LOGIN");
filterChain.doFilter(request, response);
return;
}
@@ -48,26 +60,22 @@ protected void doFilterInternal(
filterChain.doFilter(request, response);
return;
}
- jwt = authHeader.substring(7);
+ jwt = authHeader.substring(JwtProperties.START_OF_TOKEN);
var email = jwtService.extractSub(jwt);
String token;
var pathContainsRefreshToken = path.contains("/refresh-token");
- if(pathContainsRefreshToken){
- log.info("Refresh token getting");
+ if (pathContainsRefreshToken) {
token = tokenRepository.getRefreshToken(email);
- }else{
- log.info("Access token getting");
+ } else {
token = tokenRepository.getAccessToken(email);
}
- log.info("Token: " + token);
- log.info("JWT: " + jwt);
if (!token.equals(jwt)) {
tokenRepository.deleteAllTokensByUserEmail(email);
return;
}
- UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
+ var authToken = new UsernamePasswordAuthenticationToken(
userDetailsService.loadUserByUsername(email),
null,
null
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/LogautHandlerImpl.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/LogautHandlerImpl.java
index 9808396..34eefa0 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/LogautHandlerImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/LogautHandlerImpl.java
@@ -2,6 +2,7 @@
import com.github.asavershin.api.application.out.TokenRepository;
import com.github.asavershin.api.application.in.services.user.JwtService;
+import com.github.asavershin.api.config.properties.JwtProperties;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
@@ -12,22 +13,34 @@
@Service
@RequiredArgsConstructor
public class LogautHandlerImpl implements LogoutHandler {
-
- private final TokenRepository tokenService;
+ /**
+ * TokenRepository dependency.
+ */
+ private final TokenRepository tokenRepository;
+ /**
+ * JwtService dependency.
+ */
private final JwtService jwtService;
+ /**
+ * Not final to allow spring using proxy.
+ *
+ * @param request the HTTP request
+ * @param response the HTTP response
+ * @param authentication the current principal details
+ */
@Override
public void logout(
- HttpServletRequest request,
- HttpServletResponse response,
- Authentication authentication
+ final HttpServletRequest request,
+ final HttpServletResponse response,
+ final Authentication authentication
) {
final String authHeader = request.getHeader("Authorization");
final String jwt;
- if (authHeader == null ||!authHeader.startsWith("Bearer ")) {
+ if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return;
}
- jwt = authHeader.substring(7);
- tokenService.deleteAllTokensByUserEmail("asd");
+ jwt = authHeader.substring(JwtProperties.START_OF_TOKEN);
+ tokenRepository.deleteAllTokensByUserEmail(jwtService.extractSub(jwt));
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/SecurityConfiguration.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/SecurityConfiguration.java
index a718077..b39bcdc 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/SecurityConfiguration.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/SecurityConfiguration.java
@@ -3,7 +3,6 @@
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -20,7 +19,9 @@
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfiguration {
-
+ /**
+ * Routes that will not be subject to spring security.
+ */
private static final String[] WHITE_LIST_URL = {
"api/v1/auth/register",
"api/v1/auth/login",
@@ -35,11 +36,35 @@ public class SecurityConfiguration {
"/webjars/**",
"/swagger-ui.html",
"/docs"};
+ /**
+ * A reference to the JwtAuthenticationFilter instance.
+ */
private final JwtAuthenticationFilter jwtAuthFilter;
+
+ /**
+ * A reference to the LogoutHandler instance.
+ */
private final LogoutHandler logoutHandler;
+ /**
+ * Creates a SecurityFilterChain instance,
+ * which is used to secure the application.
+ * It configures the security filter chain to disable CSRF protection,
+ * allow access to the specified URLs without authentication,
+ * and add the JwtAuthenticationFilter
+ * before the UsernamePasswordAuthenticationFilter.
+ * It also configures the logout functionality
+ * to use the specified logout handler and clear
+ * the security context after logout.
+ *
+ * @param http the HttpSecurity instance to configure
+ * @return the SecurityFilterChain instance
+ * @throws Exception if an error occurs during configuration
+ */
@Bean
- public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ public SecurityFilterChain securityFilterChain(
+ final HttpSecurity http
+ ) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(req ->
@@ -48,15 +73,22 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.anyRequest()
.authenticated()
)
- .sessionManagement(session -> session.sessionCreationPolicy(NEVER))
- .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
+ .sessionManagement(
+ session -> session.sessionCreationPolicy(NEVER)
+ )
+ .addFilterBefore(
+ jwtAuthFilter,
+ UsernamePasswordAuthenticationFilter.class
+ )
.logout(logout ->
logout.logoutUrl("/auth/logout")
.addLogoutHandler(logoutHandler)
- .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext())
- )
- ;
-
+ .logoutSuccessHandler(
+ (request, response, authentication)
+ -> SecurityContextHolder
+ .clearContext()
+ )
+ );
return http.build();
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/UserDetailsServiceImpl.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/UserDetailsServiceImpl.java
index cebe0f0..b34c970 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/UserDetailsServiceImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/UserDetailsServiceImpl.java
@@ -10,10 +10,30 @@
@Service
@RequiredArgsConstructor
-public class UserDetailsServiceImpl extends IsEntityFound implements UserDetailsService {
+public class UserDetailsServiceImpl
+ extends IsEntityFound implements UserDetailsService {
+ /**
+ * The AuthenticatedUserRepository
+ * dependency is used to fetch the User entity from the database.
+ */
private final AuthenticatedUserRepository repository;
+ /**
+ * The loadUserByUsername method is an implementation
+ * of the UserDetailsService interface.
+ * It is responsible for loading a UserDetails object
+ * based on the provided username.
+ * Not final to allow spring use proxy.
+ *
+ * @param username The username of the User to be loaded.
+ * @return A UserDetails object
+ * representing the User with the provided username.
+ * @throws UsernameNotFoundException If the User with
+ * the provided username is not found.
+ */
@Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ public UserDetails loadUserByUsername(
+ final String username
+ ) throws UsernameNotFoundException {
var authenticatedUser = repository.findByEmail(username);
isEntityFound(authenticatedUser, "User", "email", username);
return new CustomUserDetails(authenticatedUser);
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/package-info.java
new file mode 100644
index 0000000..3f89ddd
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/in/security/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains logic for security like filter chains,
+ * user details ant others.
+ */
+package com.github.asavershin.api.infrastructure.in.security;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/AuthenticatedUserRepositoryImpl.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/AuthenticatedUserRepositoryImpl.java
index 3402186..e381f04 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/AuthenticatedUserRepositoryImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/AuthenticatedUserRepositoryImpl.java
@@ -14,10 +14,18 @@
@Repository
@RequiredArgsConstructor
-public class AuthenticatedUserRepositoryImpl implements AuthenticatedUserRepository, RecordMapper {
+public class AuthenticatedUserRepositoryImpl
+ implements AuthenticatedUserRepository,
+ RecordMapper {
+ /**
+ * The DSLContext object is used to interact with the database.
+ */
private final DSLContext dslContext;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public AuthenticatedUser findByEmail(String email) {
+ public AuthenticatedUser findByEmail(final String email) {
return dslContext.select(
USERS.USER_ID,
USERS.USER_EMAIL,
@@ -28,12 +36,16 @@ public AuthenticatedUser findByEmail(String email) {
.fetchOne(this);
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public AuthenticatedUser map(Record record) {
+ public AuthenticatedUser map(final Record record) {
var userId = record.get(USERS.USER_ID);
var email = record.get(USERS.USER_EMAIL);
var password = record.get(USERS.USER_PASSWORD);
- return AuthenticatedUser.founded(new UserId(userId), new Credentials(email, password));
+ return AuthenticatedUser.founded(
+ new UserId(userId), new Credentials(email, password)
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/CacheRepositoryIml.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/CacheRepositoryIml.java
deleted file mode 100644
index 48ea8ba..0000000
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/CacheRepositoryIml.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.github.asavershin.api.infrastructure.out.persistence;
-
-import com.github.asavershin.api.application.out.CacheRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.stereotype.Repository;
-
-import java.util.concurrent.TimeUnit;
-
-@Repository
-@RequiredArgsConstructor
-public class CacheRepositoryIml implements CacheRepository {
- private final RedisTemplate redisTemplate;
- @Override
- public void addCache(String key, String token, long expiration) {
- redisTemplate.opsForValue().set(key, token, expiration, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public String getCache(String key) {
- return (String) redisTemplate.opsForValue().get(key);
- }
-
- @Override
- public void deleteCache(String key) {
- redisTemplate.delete(key);
- }
-}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/ImageRepositoryImpl.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/ImageRepositoryImpl.java
index d462f00..3cddeba 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/ImageRepositoryImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/ImageRepositoryImpl.java
@@ -1,7 +1,11 @@
package com.github.asavershin.api.infrastructure.out.persistence;
import com.github.asavershin.api.domain.PartOfResources;
-import com.github.asavershin.api.domain.image.*;
+import com.github.asavershin.api.domain.image.Image;
+import com.github.asavershin.api.domain.image.ImageId;
+import com.github.asavershin.api.domain.image.ImageNameWithExtension;
+import com.github.asavershin.api.domain.image.ImageRepository;
+import com.github.asavershin.api.domain.image.MetaData;
import com.github.asavershin.api.domain.user.UserId;
import lombok.RequiredArgsConstructor;
import org.jooq.DSLContext;
@@ -16,17 +20,28 @@
@Repository
@RequiredArgsConstructor
-public class ImageRepositoryImpl implements ImageRepository, RecordMapper {
+public class ImageRepositoryImpl
+ implements ImageRepository, RecordMapper {
+ /**
+ * The DSLContext object is used to interact with the database.
+ */
private final DSLContext dslContext;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void save(Image image) {
+ public void save(final Image image) {
dslContext.insertInto(IMAGE)
.set(IMAGE.IMAGE_ID, image.imageId().value())
- .set(IMAGE.IMAGE_NAME, image.metaInfo().imageNameWithExtension().imageName())
+ .set(
+ IMAGE.IMAGE_NAME,
+ image.metaInfo().imageNameWithExtension().imageName()
+ )
.set(IMAGE.IMAGE_SIZE, image.metaInfo().imageSize())
.set(IMAGE.IMAGE_EXTENSION,
- image.metaInfo().imageNameWithExtension().imageExtension().toString())
+ image.metaInfo().imageNameWithExtension()
+ .imageExtension().toString())
.execute();
dslContext.insertInto(USER_IMAGES)
.set(USER_IMAGES.IMAGE_ID, image.imageId().value())
@@ -34,34 +49,44 @@ public void save(Image image) {
.execute();
}
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public List findImagesByUserId(UserId userId, PartOfResources partOfResources) {
+ public List findImagesByUserId(final UserId userId,
+ final PartOfResources page) {
return dslContext.select(IMAGE.fields()).select(USER_IMAGES.USER_ID)
.from(IMAGE)
.join(USER_IMAGES).using(IMAGE.IMAGE_ID)
- .offset(partOfResources.pageNumber() * partOfResources.pageSize())
- .limit(partOfResources.pageSize())
+ .offset(page.pageNumber() * page.pageSize())
+ .limit(page.pageSize())
.fetch(this);
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public Image findImageByImageId(ImageId imageId) {
+ public Image findImageByImageId(final ImageId imageId) {
return dslContext.select(IMAGE.fields()).select(USER_IMAGES.USER_ID)
.from(IMAGE)
.join(USER_IMAGES).using(IMAGE.IMAGE_ID)
.where(IMAGE.IMAGE_ID.eq(imageId.value()))
.fetchOne(this);
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void deleteImageByImageId(Image imageId) {
+ public void deleteImageByImageId(final Image imageId) {
dslContext.deleteFrom(IMAGE)
.where(IMAGE.IMAGE_ID.eq(imageId.imageId().value()))
.execute();
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public Image map(Record record) {
+ public Image map(final Record record) {
var imageId = record.get(IMAGE.IMAGE_ID);
var imageName = record.get(IMAGE.IMAGE_NAME);
var userId = record.get(USER_IMAGES.USER_ID);
@@ -69,7 +94,13 @@ public Image map(Record record) {
var imageExtension = record.get(IMAGE.IMAGE_EXTENSION);
return new Image(
new ImageId(imageId),
- new MetaInfo(ImageNameWithExtension.founded(imageName, imageExtension), imageSize),
+ new MetaData(
+ ImageNameWithExtension.founded(
+ imageName,
+ imageExtension
+ ),
+ imageSize
+ ),
new UserId(userId)
);
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/TokenRepositoryIml.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/TokenRepositoryIml.java
deleted file mode 100644
index 63095fd..0000000
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/TokenRepositoryIml.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.github.asavershin.api.infrastructure.out.persistence;
-
-import com.github.asavershin.api.application.out.CacheRepository;
-import com.github.asavershin.api.application.out.TokenRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Repository;
-
-@Repository
-@RequiredArgsConstructor
-public class TokenRepositoryIml implements TokenRepository {
- private final String refreshKey = "REFRESH_TOKEN_";
- private final String accessKey = "ACCESS_TOKEN_";
- private final CacheRepository cacheRepository;
-
- @Override
- public String getAccessToken(String email){
- return cacheRepository.getCache(accessKey + email);
- }
-
- @Override
- public String getRefreshToken(String email){
- return cacheRepository.getCache(refreshKey + email);
- }
-
- @Override
- public void saveRefreshToken(String username, String jwtToken, Long expiration) {
- cacheRepository.addCache(refreshKey + username, jwtToken, expiration);
- }
-
- @Override
- public void saveAccessToken(String username, String jwtToken, Long expiration) {
- cacheRepository.addCache(accessKey + username, jwtToken, expiration);
- }
-
- @Override
- public void deleteAllTokensByUserEmail(String username) {
- cacheRepository.deleteCache(refreshKey + username);
- cacheRepository.deleteCache(accessKey+ username);
- }
-}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/UserRepositoryImpl.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/UserRepositoryImpl.java
index a20bac2..4b43728 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/UserRepositoryImpl.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/UserRepositoryImpl.java
@@ -12,11 +12,16 @@
@Repository
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserRepository {
-
+ /**
+ * The DSLContext object is used to interact with the database.
+ */
private final DSLContext dslContext;
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public void save(User newUser) {
+ public void save(final User newUser) {
UsersRecord userRecord = dslContext.newRecord(USERS);
userRecord.setUserId(newUser.userId().value());
userRecord.setUserFirstname(newUser.userCredentials().email());
@@ -28,9 +33,13 @@ public void save(User newUser) {
.set(userRecord)
.execute();
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public boolean existByUserEmail(String email) {
- return dslContext.fetchExists(USERS, USERS.USER_EMAIL.eq(email));
+ public boolean existByUserEmail(final String email) {
+ return dslContext.fetchExists(
+ USERS, USERS.USER_EMAIL.eq(email)
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/package-info.java
new file mode 100644
index 0000000..5ee66da
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/persistence/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains SQL repositories.
+ * @author asavershin
+ */
+package com.github.asavershin.api.infrastructure.out.persistence;
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/CacheRepositoryIml.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/CacheRepositoryIml.java
new file mode 100644
index 0000000..51e0422
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/CacheRepositoryIml.java
@@ -0,0 +1,45 @@
+package com.github.asavershin.api.infrastructure.out.storage;
+
+import com.github.asavershin.api.application.out.CacheRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Repository;
+
+import java.util.concurrent.TimeUnit;
+
+@Repository
+@RequiredArgsConstructor
+public class CacheRepositoryIml implements CacheRepository {
+ /**
+ * Redis template is used to interact with redis server.
+ */
+ private final RedisTemplate redisTemplate;
+
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public void addCache(final String key,
+ final String token,
+ final long expiration) {
+ redisTemplate.opsForValue().set(
+ key, token, expiration, TimeUnit.MILLISECONDS
+ );
+ }
+
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public String getCache(final String key) {
+ return (String) redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public void deleteCache(final String key) {
+ redisTemplate.delete(key);
+ }
+}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/FileException.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/FileException.java
index 9904ffe..e7c3567 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/FileException.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/FileException.java
@@ -1,7 +1,12 @@
package com.github.asavershin.api.infrastructure.out.storage;
public class FileException extends RuntimeException {
- public FileException(String s) {
+ /**
+ * Constructs a new FileException with the specified detail message.
+ *
+ * @param s the detail message
+ */
+ public FileException(final String s) {
super(s);
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/MinioServiceIml.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/MinioServiceIml.java
index 8eef78b..055f46b 100644
--- a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/MinioServiceIml.java
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/MinioServiceIml.java
@@ -3,8 +3,12 @@
import com.github.asavershin.api.application.out.MinioService;
import com.github.asavershin.api.config.properties.MinIOProperties;
-import io.minio.*;
-import lombok.RequiredArgsConstructor;
+import io.minio.BucketExistsArgs;
+import io.minio.GetObjectArgs;
+import io.minio.MakeBucketArgs;
+import io.minio.MinioClient;
+import io.minio.PutObjectArgs;
+import io.minio.RemoveObjectArgs;
import lombok.SneakyThrows;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.stereotype.Service;
@@ -12,30 +16,47 @@
import java.io.InputStream;
import java.util.List;
-import java.util.UUID;
@Service
public class MinioServiceIml implements MinioService {
+ /**
+ * The MinioClient is used to interact with the MinIO server.
+ */
private final MinioClient minioClient;
+ /**
+ * The MinIO properties from .yml.
+ */
private final MinIOProperties minioProperties;
-
- public MinioServiceIml(MinioClient minioClient, MinIOProperties minioProperties) {
- this.minioClient = minioClient;
- this.minioProperties = minioProperties;
+ /**
+ * Constructor for {@link MinioServiceIml}.
+ *
+ * @param aMinioClient The {@link MinioClient}
+ * instance to interact with the MinIO server.
+ * @param aMinioProperties The {@link MinIOProperties}
+ * instance containing the configuration
+ * for the MinIO server.
+ */
+ public MinioServiceIml(final MinioClient aMinioClient,
+ final MinIOProperties aMinioProperties) {
+ this.minioClient = aMinioClient;
+ this.minioProperties = aMinioProperties;
createBucket();
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
- public String saveFile(final MultipartFile image) {
+ public void saveFile(final MultipartFile image, final String filename) {
if (!bucketExists(minioProperties.getBucket())) {
- throw new FileException("File upload failed: bucket does not exist");
+ throw new FileException(
+ "File upload failed: bucket does not exist"
+ );
}
if (image.isEmpty() || image.getOriginalFilename() == null) {
throw new FileException("File must have name");
}
- var link = generateFileName();
InputStream inputStream;
try {
inputStream = image.getInputStream();
@@ -43,17 +64,19 @@ public String saveFile(final MultipartFile image) {
throw new FileException("File upload failed: "
+ e.getMessage());
}
- saveImage(inputStream, link);
- return link;
+ saveFile(inputStream, filename);
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
public byte[] getFile(final String link) {
if (link == null) {
throw new FileException("File download failed: link is nullable");
}
try {
- return IOUtils.toByteArray(minioClient.getObject(GetObjectArgs.builder()
+ return IOUtils.toByteArray(
+ minioClient.getObject(GetObjectArgs.builder()
.bucket(minioProperties.getBucket())
.object(link)
.build()));
@@ -61,7 +84,9 @@ public byte[] getFile(final String link) {
throw new FileException("File download failed: " + e.getMessage());
}
}
-
+ /**
+ * Not final to allow spring use proxy.
+ */
@Override
public void deleteFiles(final List links) {
if (links == null || links.isEmpty()) {
@@ -96,7 +121,7 @@ private void createBucket() {
}
@SneakyThrows
- private void saveImage(
+ private void saveFile(
final InputStream inputStream,
final String fileName
) {
@@ -107,12 +132,10 @@ private void saveImage(
.build());
}
- private String generateFileName() {
- return UUID.randomUUID().toString();
- }
-
@SneakyThrows(Exception.class)
- private boolean bucketExists(String bucketName) {
- return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+ private boolean bucketExists(final String bucketName) {
+ return minioClient.bucketExists(
+ BucketExistsArgs.builder().bucket(bucketName).build()
+ );
}
}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/TokenRepositoryIml.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/TokenRepositoryIml.java
new file mode 100644
index 0000000..6344c09
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/TokenRepositoryIml.java
@@ -0,0 +1,67 @@
+package com.github.asavershin.api.infrastructure.out.storage;
+
+import com.github.asavershin.api.application.out.CacheRepository;
+import com.github.asavershin.api.application.out.TokenRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@RequiredArgsConstructor
+public class TokenRepositoryIml implements TokenRepository {
+ /**
+ * The prefix for access tokens in the cache.
+ */
+ private final String accessKey = "ACCESS_TOKEN_";
+
+ /**
+ * The prefix for refresh tokens in the cache.
+ */
+ private final String refreshKey = "REFRESH_TOKEN_";
+
+ /**
+ * CacheRepository instance for storing and retrieving tokens.
+ */
+ private final CacheRepository cacheRepository;
+
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public String getAccessToken(final String email) {
+ return cacheRepository.getCache(accessKey + email);
+ }
+
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public String getRefreshToken(final String email) {
+ return cacheRepository.getCache(refreshKey + email);
+ }
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public void saveRefreshToken(final String username,
+ final String jwtToken,
+ final Long expiration) {
+ cacheRepository.addCache(refreshKey + username, jwtToken, expiration);
+ }
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public void saveAccessToken(final String username,
+ final String jwtToken,
+ final Long expiration) {
+ cacheRepository.addCache(accessKey + username, jwtToken, expiration);
+ }
+ /**
+ * Not final to allow spring use proxy.
+ */
+ @Override
+ public void deleteAllTokensByUserEmail(final String username) {
+ cacheRepository.deleteCache(refreshKey + username);
+ cacheRepository.deleteCache(accessKey + username);
+ }
+}
diff --git a/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/package-info.java b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/package-info.java
new file mode 100644
index 0000000..a094d40
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/infrastructure/out/storage/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains impl of noSQL storages.
+ * @author asavershin
+ */
+package com.github.asavershin.api.infrastructure.out.storage;
diff --git a/api/src/main/java/com/github/asavershin/api/package-info.java b/api/src/main/java/com/github/asavershin/api/package-info.java
new file mode 100644
index 0000000..a3a5220
--- /dev/null
+++ b/api/src/main/java/com/github/asavershin/api/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * This package contains the API for the application.
+ * Implementation of a microservice that directly interacts with the user.
+ * @author asavershin
+ */
+package com.github.asavershin.api;
diff --git a/api/src/test/java/com/github/asavershin/api/common/ImageHelper.java b/api/src/test/java/com/github/asavershin/api/common/ImageHelper.java
index 004de07..6cd6c04 100644
--- a/api/src/test/java/com/github/asavershin/api/common/ImageHelper.java
+++ b/api/src/test/java/com/github/asavershin/api/common/ImageHelper.java
@@ -2,7 +2,7 @@
import com.github.asavershin.api.domain.image.ImageId;
import com.github.asavershin.api.domain.image.ImageNameWithExtension;
-import com.github.asavershin.api.domain.image.MetaInfo;
+import com.github.asavershin.api.domain.image.MetaData;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
@@ -11,12 +11,12 @@ public class ImageHelper {
public static ImageId imageId(){
return ImageId.nextIdentity();
}
- public static MetaInfo metaInfo1(){
- return new MetaInfo(ImageNameWithExtension.fromOriginalFileName("image.jpg"), 1L);
+ public static MetaData metaInfo1(){
+ return new MetaData(ImageNameWithExtension.fromOriginalFileName("image.jpg"), 1L);
}
- public static MetaInfo metaInfo3(){
- return new MetaInfo(ImageNameWithExtension.fromOriginalFileName("image3.jpg"), 3L);
+ public static MetaData metaInfo3(){
+ return new MetaData(ImageNameWithExtension.fromOriginalFileName("image3.jpg"), 3L);
}
public static MultipartFile multipartFile1() {
diff --git a/api/src/test/java/com/github/asavershin/api/domaintest/ImageTest.java b/api/src/test/java/com/github/asavershin/api/domaintest/ImageTest.java
index 24d597c..0790394 100644
--- a/api/src/test/java/com/github/asavershin/api/domaintest/ImageTest.java
+++ b/api/src/test/java/com/github/asavershin/api/domaintest/ImageTest.java
@@ -5,7 +5,7 @@
import com.github.asavershin.api.domain.ResourceOwnershipException;
import com.github.asavershin.api.domain.image.Image;
import com.github.asavershin.api.domain.image.ImageId;
-import com.github.asavershin.api.domain.image.MetaInfo;
+import com.github.asavershin.api.domain.image.MetaData;
import com.github.asavershin.api.domain.user.UserId;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -16,7 +16,7 @@ public class ImageTest {
void testAddNewImage() {
//Given
ImageId imageId = ImageHelper.imageId();
- MetaInfo metaInfo = ImageHelper.metaInfo1();
+ MetaData metaInfo = ImageHelper.metaInfo1();
UserId userId = UserHelper.UserId();
//When
@@ -32,7 +32,7 @@ void testAddNewImage() {
void testFoundedImage() {
//Given
ImageId imageId = ImageHelper.imageId();
- MetaInfo metaInfo = ImageHelper.metaInfo1();
+ MetaData metaInfo = ImageHelper.metaInfo1();
UserId userId = UserHelper.UserId();
// When
Image image = new Image(imageId, metaInfo, userId);
@@ -46,7 +46,7 @@ void testFoundedImage() {
void testBelongsToUser() {
// Given
ImageId imageId = ImageHelper.imageId();
- MetaInfo metaInfo = ImageHelper.metaInfo1();
+ MetaData metaInfo = ImageHelper.metaInfo1();
UserId userId = UserHelper.UserId();
UserId otherUserId = UserHelper.UserId();
@@ -66,10 +66,10 @@ void testEquals() {
var imageId = ImageId.nextIdentity();
var userId = UserId.nextIdentity();
- MetaInfo metaInfo1 = ImageHelper.metaInfo1();
+ MetaData metaInfo1 = ImageHelper.metaInfo1();
Image image1 = new Image(imageId, metaInfo1, userId);
- MetaInfo metaInfo2 = ImageHelper.metaInfo1();
+ MetaData metaInfo2 = ImageHelper.metaInfo1();
Image image2 = new Image(imageId, metaInfo2, userId);
assertTrue(image1.equals(image2));
@@ -80,7 +80,7 @@ void testEquals() {
assertFalse(image1.equals(null));
ImageId imageId3 = ImageId.nextIdentity();
- MetaInfo metaInfo3 = ImageHelper.metaInfo3();
+ MetaData metaInfo3 = ImageHelper.metaInfo3();
UserId userId3 = UserHelper.UserId();
Image image3 = new Image(imageId3, metaInfo3, userId3);
diff --git a/api/src/test/java/com/github/asavershin/api/integrations/ImageLogicTest.java b/api/src/test/java/com/github/asavershin/api/integrations/ImageLogicTest.java
index a1ca5f8..48b77a0 100644
--- a/api/src/test/java/com/github/asavershin/api/integrations/ImageLogicTest.java
+++ b/api/src/test/java/com/github/asavershin/api/integrations/ImageLogicTest.java
@@ -20,6 +20,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -78,6 +79,8 @@ public void clearDB(){
e.printStackTrace();
}
}
+ @Autowired
+ private ApplicationContext applicationContext;
@Test
public void storeImageTest(){
@@ -91,6 +94,8 @@ public void storeImageTest(){
var user = authenticatedUserRepository.findByEmail(credentials.email());
// When
var imageId = imageService.storeImage(user.userId(), ImageHelper.multipartFile1());
+ log.info("asdasd");
+ log.info(applicationContext.getBean(ImageService.class, "foo").getClass().toString());
// Then
var image = imageRepository.findImageByImageId(imageId);
@@ -117,6 +122,7 @@ public void storeImageWithIllegalExtensionTest(){
registerNewUser.register(fullName,credentials);
var user = authenticatedUserRepository.findByEmail(credentials.email());
+ assertNotNull(user);
// When
var ex = assertThrows(IllegalArgumentException.class, () -> imageService.storeImage(user.userId(), ImageHelper.multipartFileWithIllegalException()));
diff --git a/pom.xml b/pom.xml
index a9fba13..8a09635 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,10 +19,11 @@
- 22
- 22
+ 21
+ 21
UTF-8
1.18.30
+ 3.3.1
@@ -46,4 +47,14 @@
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ ${maven-checkstyle-plugin.version}
+
+
+
+