diff --git a/src/main/java/ru/soune/nocopy/controller/ApiController.java b/src/main/java/ru/soune/nocopy/controller/ApiController.java index 4026dfe..73c505c 100644 --- a/src/main/java/ru/soune/nocopy/controller/ApiController.java +++ b/src/main/java/ru/soune/nocopy/controller/ApiController.java @@ -391,6 +391,18 @@ public class ApiController { Long userId = authService.useUserAuthToken(tokenHeader); FileEntityResponse entityResponse = fileEntityService.getById(fileId, version); + FileStatus status = entityResponse.getStatus(); + + if (status.equals(FileStatus.BLOCKED) || status.equals(FileStatus.DELETED) || + status.equals(FileStatus.REMOVED)) { + Map errorData = new HashMap<>(); + errorData.put("fileId", entityResponse.getId()); + + return ResponseEntity.ok().body(new BaseResponse(20004, + MessageCode.FILE_IS_BLOCKED.getCode(), + MessageCode.FILE_IS_BLOCKED.getDescription(), + errorData)); + } User fileUser = userRepository.findById(entityResponse.getUserId()).orElseThrow(); User user = userRepository.findById(userId).orElseThrow(); diff --git a/src/main/java/ru/soune/nocopy/dto/MessageCode.java b/src/main/java/ru/soune/nocopy/dto/MessageCode.java index 886c0b3..522dca1 100644 --- a/src/main/java/ru/soune/nocopy/dto/MessageCode.java +++ b/src/main/java/ru/soune/nocopy/dto/MessageCode.java @@ -5,6 +5,7 @@ public enum MessageCode { REG_EMAIL_EXISTS(1, "Email already registered"), REG_EMAIL_OR_PHONE_EXISTS(1, "Email or phone already registered"), REFERRAL_LINK_IS_NOT_EXIST(1, "Refferal link is not exist"), + FILE_IS_BLOCKED(1, "File is blocked,deleted or removed"), INVALID_FIELD(2, "Invalid field"), MAIL_VERIFIED_NULL(2, "Mail verified null"), INVALID_TOKEN(2, "Token not found or time expired"), diff --git a/src/main/java/ru/soune/nocopy/dto/complaint/ComplaintResponse.java b/src/main/java/ru/soune/nocopy/dto/complaint/ComplaintResponse.java index 55efa91..1fe00ac 100644 --- a/src/main/java/ru/soune/nocopy/dto/complaint/ComplaintResponse.java +++ b/src/main/java/ru/soune/nocopy/dto/complaint/ComplaintResponse.java @@ -33,4 +33,7 @@ public class ComplaintResponse { @JsonProperty("updated_at") private String updatedAt; + + @JsonProperty("not_moderated") + private Boolean notModerated; } diff --git a/src/main/java/ru/soune/nocopy/dto/file/SimilarFileDTO.java b/src/main/java/ru/soune/nocopy/dto/file/SimilarFileDTO.java index 971bbd5..d94b0c2 100644 --- a/src/main/java/ru/soune/nocopy/dto/file/SimilarFileDTO.java +++ b/src/main/java/ru/soune/nocopy/dto/file/SimilarFileDTO.java @@ -20,4 +20,5 @@ public class SimilarFileDTO { LocalDateTime uploadDate; String url; Boolean owner; + String fileStatus; } diff --git a/src/main/java/ru/soune/nocopy/entity/complaint/ComplaintEntity.java b/src/main/java/ru/soune/nocopy/entity/complaint/ComplaintEntity.java index ab2b573..acb19e9 100644 --- a/src/main/java/ru/soune/nocopy/entity/complaint/ComplaintEntity.java +++ b/src/main/java/ru/soune/nocopy/entity/complaint/ComplaintEntity.java @@ -52,4 +52,7 @@ public class ComplaintEntity { @Column(name = "updated_at") @LastModifiedDate private LocalDateTime updatedAt; + + @Column(name = "not_moderated_file") + private Boolean not_moderated_file; } diff --git a/src/main/java/ru/soune/nocopy/entity/file/FileEntity.java b/src/main/java/ru/soune/nocopy/entity/file/FileEntity.java index 02104c7..a02e1cc 100644 --- a/src/main/java/ru/soune/nocopy/entity/file/FileEntity.java +++ b/src/main/java/ru/soune/nocopy/entity/file/FileEntity.java @@ -87,6 +87,9 @@ public class FileEntity { @Column(name = "medium_path") private String mediumPath; + @Column(name = "moderation_reason_id") + private Long moderationReasonId; + @OneToOne(mappedBy = "file", cascade = CascadeType.ALL, orphanRemoval = true) @JsonIgnore private ImageHashEntity imageHash; diff --git a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java index cdd4fc1..a23ead9 100644 --- a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java +++ b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java @@ -7,5 +7,8 @@ public enum FileStatus { VIOLATION, CHECKED, ERROR, - TEMP + TEMP, + REMOVED, + MODERATION, + BLOCKED } diff --git a/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationReason.java b/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationReason.java new file mode 100644 index 0000000..e62c302 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/file/moderation/ModerationReason.java @@ -0,0 +1,34 @@ +package ru.soune.nocopy.entity.file.moderation; + +import jakarta.persistence.*; +import lombok.*; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "moderation_reasons") +@EntityListeners(AuditingEntityListener.class) +public class ModerationReason { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "reason_text", nullable = false, columnDefinition = "TEXT") + private String reasonText; + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at") + private LocalDateTime updatedAt; +} diff --git a/src/main/java/ru/soune/nocopy/handler/ComplaintEntityHandler.java b/src/main/java/ru/soune/nocopy/handler/ComplaintEntityHandler.java index a046205..c0ebc7b 100644 --- a/src/main/java/ru/soune/nocopy/handler/ComplaintEntityHandler.java +++ b/src/main/java/ru/soune/nocopy/handler/ComplaintEntityHandler.java @@ -63,6 +63,7 @@ public class ComplaintEntityHandler implements RequestHandler { "text is required"); ComplaintResponse response = complaintService.createComplaint(req); + return successResponse(msgId, "Complaint created successfully", response); } @@ -117,6 +118,7 @@ public class ComplaintEntityHandler implements RequestHandler { if (req.getId() == null) return errorResponse(msgId, MessageCode.NOT_FOUND.getCode(), "id is required"); ComplaintResponse response = complaintService.updateComplaint(req.getId(), req); + return successResponse(msgId, "Complaint updated successfully", response); } diff --git a/src/main/java/ru/soune/nocopy/repository/ImageSimilarityRepository.java b/src/main/java/ru/soune/nocopy/repository/ImageSimilarityRepository.java index 4144760..1d78c71 100644 --- a/src/main/java/ru/soune/nocopy/repository/ImageSimilarityRepository.java +++ b/src/main/java/ru/soune/nocopy/repository/ImageSimilarityRepository.java @@ -22,6 +22,7 @@ public interface ImageSimilarityRepository f.created_at AS uploadDate, f.protection_status AS protectionStatus, f.file_extension AS extension, + f.status AS status, h.hash64_hi AS hash64Hi, h.hash64_lo AS hash64Lo FROM image_hashes ref diff --git a/src/main/java/ru/soune/nocopy/repository/SimilarImageProjection.java b/src/main/java/ru/soune/nocopy/repository/SimilarImageProjection.java index 4d3f47f..cf3fe4b 100644 --- a/src/main/java/ru/soune/nocopy/repository/SimilarImageProjection.java +++ b/src/main/java/ru/soune/nocopy/repository/SimilarImageProjection.java @@ -15,4 +15,5 @@ public interface SimilarImageProjection { LocalDateTime getUploadDate(); ProtectionStatus getProtectionStatus(); String getExtension(); + String getFileStatus(); } \ No newline at end of file diff --git a/src/main/java/ru/soune/nocopy/service/FileSimilarityService.java b/src/main/java/ru/soune/nocopy/service/FileSimilarityService.java index 2a5ea95..0db4e92 100644 --- a/src/main/java/ru/soune/nocopy/service/FileSimilarityService.java +++ b/src/main/java/ru/soune/nocopy/service/FileSimilarityService.java @@ -12,6 +12,7 @@ import org.springframework.stereotype.Service; import ru.soune.nocopy.dto.file.SimilarFileDTO; import ru.soune.nocopy.entity.company.Company; import ru.soune.nocopy.entity.file.FileEntity; +import ru.soune.nocopy.entity.file.FileStatus; import ru.soune.nocopy.entity.file.ImageHashEntity; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.DuplicateImageException; @@ -154,22 +155,19 @@ public class FileSimilarityService { var imageHashEntity = hashRepository.findById(fileId) .orElseThrow(() -> new RuntimeException("Hash not found for file: " + fileId)); - List candidates; + List userIds; -// if (authToken == null || "all".equals(authToken)) { - candidates = repository.findCandidates(fileId); -// } else { - Long userId = authTokenRepository.findUserIdByToken(authToken); - User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found")); - Company company = user.getCompany(); - if (company != null) { - userIds = company.getUsers().stream().map(User::getId).collect(Collectors.toList()); -// candidates = repository.findCandidatesFromUserFiles(fileId, userIds); - } else { - userIds = List.of(userId); -// candidates = repository.findCandidatesFromUserFiles(fileId, userId); - } -// } + List candidates = repository.findCandidates(fileId); + + Long userId = authTokenRepository.findUserIdByToken(authToken); + User user = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("User not found")); + Company company = user.getCompany(); + + if (company != null) { + userIds = company.getUsers().stream().map(User::getId).collect(Collectors.toList()); + } else { + userIds = List.of(userId); + } List levels = (similarityLevels != null && !similarityLevels.isEmpty()) ? similarityLevels @@ -180,6 +178,7 @@ public class FileSimilarityService { imageHashEntity.getHash64Hi(), imageHashEntity.getHash64Lo(), userIds)) .filter(dto -> levels.contains(dto.getSimilarityLevel())) + .filter(dto -> dto.getFileStatus().equals(FileStatus.ACTIVE.name())) .sorted(Comparator.comparingInt(SimilarFileDTO::getHammingDistance)) .collect(Collectors.toList()); @@ -243,6 +242,7 @@ public class FileSimilarityService { .owner(userIds.contains(similarImageProjection.getUserId())) // .url(baseUrl + "/api/files/protected/" + similarImageProjection.getId()) .url(baseUrl + "/api/files/protected/" + similarImageProjection.getId() + "/thumbnail") + .fileStatus(similarImageProjection.getFileStatus()) .build(); } diff --git a/src/main/java/ru/soune/nocopy/service/complaint/ComplaintEntityService.java b/src/main/java/ru/soune/nocopy/service/complaint/ComplaintEntityService.java index 0e9b959..bf6f509 100644 --- a/src/main/java/ru/soune/nocopy/service/complaint/ComplaintEntityService.java +++ b/src/main/java/ru/soune/nocopy/service/complaint/ComplaintEntityService.java @@ -12,6 +12,7 @@ import ru.soune.nocopy.dto.complaint.ComplaintRequest; import ru.soune.nocopy.dto.complaint.ComplaintResponse; import ru.soune.nocopy.entity.complaint.ComplaintEntity; import ru.soune.nocopy.entity.complaint.ComplaintStatus; +import ru.soune.nocopy.entity.file.FileStatus; import ru.soune.nocopy.entity.violation.Violation; import ru.soune.nocopy.exception.ComplaintNotFoundException; import ru.soune.nocopy.exception.DuplicateComplaintException; @@ -32,8 +33,6 @@ public class ComplaintEntityService { private final ViolationRepository violationRepository; - private final ObjectMapper objectMapper; - private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public ComplaintResponse createComplaint(ComplaintRequest request) { @@ -49,6 +48,7 @@ public class ComplaintEntityService { .complaintText(request.getComplaintText()) .email(request.getEmail()) .violation(violation) + .not_moderated_file(violation.getFileEntity().getStatus().equals(FileStatus.MODERATION)) .build(); return mapToResponse(complaintRepository.save(complaint)); @@ -116,6 +116,7 @@ public class ComplaintEntityService { .violationId(entity.getViolation() != null ? entity.getViolation().getId() : null) .createdAt(entity.getCreatedAt() != null ? entity.getCreatedAt().format(DATE_FORMATTER) : null) .updatedAt(entity.getUpdatedAt() != null ? entity.getUpdatedAt().format(DATE_FORMATTER) : null) + .notModerated(entity.getNot_moderated_file() != null ? entity.getNot_moderated_file() : null) .build(); } }