Merge branch 'dev' into NCBACK-33

# Conflicts:
#	src/main/java/ru/soune/nocopy/entity/file/ImageProtection.java
#	src/main/java/ru/soune/nocopy/entity/user/User.java
#	src/main/java/ru/soune/nocopy/handler/ImageFoundRequestHandler.java
#	src/main/java/ru/soune/nocopy/repository/AuthTokenRepository.java
#	src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java
This commit is contained in:
vladp
2026-01-27 05:46:50 +07:00
47 changed files with 1458 additions and 431 deletions
@@ -1,6 +1,7 @@
package ru.soune.nocopy.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import ru.soune.nocopy.entity.user.AuthToken;
@@ -13,6 +14,11 @@ public interface AuthTokenRepository extends JpaRepository<AuthToken, Long> {
List<AuthToken> findByExpiresAtBefore(LocalDateTime expiresAtBefore);
Optional<AuthToken> findByLastUsedAtBefore(LocalDateTime lastUsedAt);
Optional<AuthToken> findByToken(String token);
@Query(value = """
SELECT a.user_id FROM auth_tokens a WHERE a.token = :token
""",
nativeQuery = true)
Long findUserIdByToken(String token);
Optional<AuthToken> findByUserIdAndIsActive(Long userId, boolean isActive);
Optional<AuthToken> findByUserId(Long userId);
}
@@ -6,14 +6,15 @@ import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.file.FileStatus;
import ru.soune.nocopy.entity.file.ProtectionStatus;
import java.util.List;
import java.util.Optional;
@Repository
public interface FileEntityRepository extends JpaRepository<FileEntity, String> {
List<FileEntity> findByUserId(Long userId);
Optional<FileEntity> findByUserIdAndChecksum(Long userId, String imageHash);
List<FileEntity> findByUserIdAndStatus(Long userId, FileStatus status);
@@ -22,16 +23,31 @@ public interface FileEntityRepository extends JpaRepository<FileEntity, String>
Optional<FileEntity> findByUploadSessionId(String uploadSessionId);
List<FileEntity> findByProtectionStatus(ProtectionStatus protectionStatus);
boolean existsByFilePath(String filePath);
@Query("SELECT SUM(f.fileSize) FROM FileEntity f WHERE f.userId = :userId AND f.status = 'ACTIVE'")
Long getTotalSizeByUserId(@Param("userId") Long userId);
@Query("SELECT f FROM FileEntity f WHERE f.protectionStatus = null AND f.status = 'ACTIVE' OR " +
"f.protectionStatus = 'NOT_PROTECTED' AND f.status = 'ACTIVE'")
List<FileEntity> findAllActiveFilesAndNotProtected();
@Query("SELECT f FROM FileEntity f WHERE f.userId = :userId AND f.originalFileName LIKE %:keyword%")
List<FileEntity> searchByFileName(@Param("userId") Long userId, @Param("keyword") String keyword);
@Query("SELECT f FROM FileEntity f WHERE f.status = :status")
List<FileEntity> searchFileEntityByStatus(@Param("status") FileStatus status);
@Query("SELECT f FROM FileEntity f WHERE f.id = :fileId")
FileEntity findByFileId(@Param("fileId") String fileId);
@Query("SELECT f FROM FileEntity f WHERE f.signature = :signature")
FileEntity findBySignature(@Param("signature") String signature);
@Query("SELECT f.id FROM FileEntity f WHERE f.filePath = :filePath")
String findFileIdByFilePath(@Param("filePath") String filePath);
long countByUserId(Long userId);
}
@@ -4,7 +4,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import ru.soune.nocopy.entity.file.ImageHashEntity;
import java.util.List;
@Repository
public interface ImageHashRepository extends JpaRepository<ImageHashEntity, String> {
void deleteByFileId(String fileId);
List<ImageHashEntity> findByFileId(String fileId);
ImageHashEntity findByHash64HiAndHash64Lo(Long hash64Hi, Long hash64Lo);
}
@@ -11,13 +11,12 @@ import java.util.List;
@Repository
public interface ImageSimilarityRepository
extends JpaRepository<FileEntity, String> {
@Query(value = """
SELECT
f.id AS similarFileId,
SELECT
f.id AS id,
f.original_file_name AS originalFileName,
f.file_size AS fileSize,
f.user_id AS userId,
h.hash64_hi AS hash64Hi,
h.hash64_lo AS hash64Lo
FROM image_hashes ref
@@ -32,6 +31,28 @@ public interface ImageSimilarityRepository
@Param("fileId") String fileId
);
@Query(value = """
SELECT
f.id AS id,
f.original_file_name AS originalFileName,
f.file_size AS fileSize,
f.user_id AS userId,
h.hash64_hi AS hash64Hi,
h.hash64_lo AS hash64Lo
FROM image_hashes ref
JOIN image_hashes h
ON ref.file_id <> h.file_id
JOIN file_entities f
ON f.id = h.file_id
WHERE ref.file_id = :fileId AND f.user_id = :userId
""",
nativeQuery = true)
List<SimilarImageProjection> findCandidatesFromUserFiles(
@Param("fileId") String fileId,
@Param("userId") Long userId
);
@Query(value = """
SELECT
h.hash64_hi AS hash64Hi,
@@ -48,7 +69,7 @@ public interface ImageSimilarityRepository
""",
nativeQuery = true)
List<SimilarImageProjection> findExactDuplicates(
@Param("hash64Hi") Integer hash64_hi,
@Param("hash64Lo") Integer hash64_lo);
@Param("hash64Hi") Long hash64_hi,
@Param("hash64Lo") Long hash64_lo);
}
@@ -1,8 +1,8 @@
package ru.soune.nocopy.repository;
public interface SimilarImageProjection {
Integer getHash64Hi();
Integer getHash64Lo();
Long getHash64Hi();
Long getHash64Lo();
String getId();
Long getUserId();
String getOriginalFileName();