NCBACK-33
Test Workflow / test (push) Successful in 3s

This commit is contained in:
vladp
2026-01-27 08:09:54 +07:00
parent 816a984891
commit 5700adafb2
9 changed files with 103 additions and 29 deletions
@@ -114,7 +114,7 @@ public class ApiController {
@RequestParam(value = "upload_id", required = false) String uploadId,
@RequestParam(value = "chunk_number", required = false) Integer chunkNumber,
@RequestParam(value = "chunk", required = false) MultipartFile chunk,
@RequestParam(value = "findSimilar", required = false) Integer findSimilar) {
@RequestParam(value = "findSimilar", required = false, defaultValue = "0") Integer findSimilar) {
try {
if (chunk == null || chunk.isEmpty()) {
return buildErrorResponse(uploadId, chunkNumber, "Chunk file null or empty");
@@ -153,11 +153,11 @@ public class ApiController {
}
}
@GetMapping("/v{version}/files/{fileId}/similar/{authToken}")
@GetMapping("/v{version}/files/{fileId}/similar")
public ResponseEntity<BaseResponse> findSimilarFiles(
@PathVariable("version") int version,
@PathVariable String fileId,
@PathVariable(required = false) String authToken,
@RequestParam(value = "auth_token",required = false) String authToken,
@RequestParam(required = false) List<String> similarityLevels,
@PageableDefault(size = 20, sort = "hammingDistance") Pageable pageable) {
SimilarityFilter filter = SimilarityFilter.builder()
@@ -443,7 +443,7 @@ public class ApiController {
throws IOException {
fileEntityService.deleteFromDisk(fileEntity);
fileEntityService.markAsDeleted(fileEntity);
fileEntityService.softDeleteFileWithHash(fileEntity);
Optional<FileEntity> originalFile = fileEntityRepository.findById(similarFiles.get(0).getFileId());
@@ -1,11 +0,0 @@
package ru.soune.nocopy.controller;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("v1/api/content")
@AllArgsConstructor
public class UserContentController {
}
@@ -2,20 +2,29 @@ package ru.soune.nocopy.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.register.ChangePasswordRequest;
import ru.soune.nocopy.dto.register.RegAnswer;
import ru.soune.nocopy.dto.register.RegRequest;
import ru.soune.nocopy.dto.user.UserDTO;
import ru.soune.nocopy.dto.user.UserRequest;
import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.entity.user.User;
import ru.soune.nocopy.exception.InvalidUserEmail;
import ru.soune.nocopy.exception.NotFoundAuthToken;
import ru.soune.nocopy.exception.NotValidFieldException;
import ru.soune.nocopy.mapper.UserMapper;
import ru.soune.nocopy.repository.AuthTokenRepository;
import ru.soune.nocopy.repository.UserRepository;
import ru.soune.nocopy.service.register.AuthService;
import ru.soune.nocopy.service.user.UserService;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RestController
@@ -31,6 +40,10 @@ public class UserController {
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;
private final AuthService authService;
@GetMapping("/all")
public ResponseEntity<List<UserDTO>> getAllUsers() {
List<UserDTO> allUsers = userRepository.findAll().stream()
@@ -108,4 +121,50 @@ public class UserController {
return ResponseEntity.ok(userService.updateUser(userRequest, user));
}
@PostMapping("/create-user")
public ResponseEntity<User> addUser(@RequestBody RegRequest registerRequest) {
if (userRepository.existsByEmail(registerRequest.getEmail()) ||
userRepository.existsByPhone(registerRequest.getPhone())) {
RegAnswer regAnswer = new RegAnswer();
regAnswer.setFieldErrors(Arrays.asList(Map.of("email", registerRequest.getEmail())));
regAnswer.setFieldErrors(Arrays.asList(Map.of("phone", registerRequest.getPhone())));
throw new NotValidFieldException("User already exists with email:" + registerRequest.getEmail() + " or phone: " +
registerRequest.getPhone(), new BaseResponse(2,
MessageCode.REG_EMAIL_OR_PHONE_EXISTS.getCode(),
MessageCode.REG_EMAIL_OR_PHONE_EXISTS.getDescription(), regAnswer));
}
User user = new User();
user.setFullName(registerRequest.getFullName());
user.setEmail(registerRequest.getEmail());
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setActive(true);
user.setEmailVerified(true);
if (registerRequest.getCompanyName() != null) {
user.setCompany(registerRequest.getCompanyName());
}
if (registerRequest.getPhone() != null) {
user.setPhone(registerRequest.getPhone());
}
User savedUser = userRepository.save(user);
AuthToken authToken = authService.generateAuthToken(savedUser);
authTokenRepository.save(authToken);
return ResponseEntity.ok().body(savedUser);
}
@DeleteMapping("/delete-user/{userId}")
public ResponseEntity<?> addUser(@PathVariable Long userId) {
userRepository.deleteById(userId);
return ResponseEntity.ok().body(Map.of("userId", userId, "deleted", "true"));
}
}
@@ -6,7 +6,6 @@ import jakarta.validation.constraints.Size;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import ru.soune.nocopy.entity.file.ImageProtection;
import ru.soune.nocopy.entity.file.Violation;
import java.time.LocalDate;
@@ -6,12 +6,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.*;
import ru.soune.nocopy.dto.file.*;
import ru.soune.nocopy.entity.user.AuthToken;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.file.FileStatus;
import ru.soune.nocopy.exception.FileEntityNotFoundException;
import ru.soune.nocopy.exception.NotFoundAuthToken;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.repository.ImageHashRepository;
import ru.soune.nocopy.service.register.AuthService;
import ru.soune.nocopy.service.file.FileEntityService;
import ru.soune.nocopy.service.file.FileStatsService;
@@ -34,6 +34,8 @@ public class FileEntityHandler implements RequestHandler {
private final FileEntityRepository fileEntityRepository;
private final ImageHashRepository imageHashRepository;
@Override
public BaseResponse handle(BaseRequest request) {
try {
@@ -273,15 +275,21 @@ public class FileEntityHandler implements RequestHandler {
FileEntity fileEntity = fileEntityRepository.findById(fileId)
.orElseThrow(() -> new FileEntityNotFoundException(fileId));
int fullDelete = fileRequest.getFullDelete() == null ? 0 : fileRequest.getFullDelete();
if (fileEntity.getStatus().equals(FileStatus.DELETED) || fileRequest.getFullDelete() == 1) {
if (fileEntity.getStatus().equals(FileStatus.DELETED) || fullDelete == 1) {
fileEntityService.deleteFromDisk(fileEntity);
response = DeleteFileResponse.builder()
.fileId(fileRequest.getFileId())
.message("File deleted from disk")
.build();
} else {
fileEntityService.markAsDeleted(fileEntity);
fileEntityService.softDeleteFileWithHash(fileEntity);
//
// imageHashRepository.deleteByFileId(fileEntity.getId());
//
// fileEntityService.markAsDeleted(fileEntity);
response = DeleteFileResponse.builder()
.fileId(fileRequest.getFileId())
.message("File marked as deleted")
@@ -7,12 +7,10 @@ import org.springframework.stereotype.Component;
import ru.soune.nocopy.dto.BaseRequest;
import ru.soune.nocopy.dto.BaseResponse;
import ru.soune.nocopy.dto.MessageCode;
import ru.soune.nocopy.dto.file.GoogleVisionSearchResponse;
import ru.soune.nocopy.dto.file.ImageSearchRequest;
import ru.soune.nocopy.dto.file.YandexSearchResponse;
import ru.soune.nocopy.service.search.YandexSearchService;
import ru.soune.nocopy.service.GoogleVisionSearchService;
import ru.soune.nocopy.service.YandexSearchService;
import ru.soune.nocopy.service.search.GoogleVisionSearchService;
@Slf4j
@Component
@@ -13,6 +13,7 @@ import ru.soune.nocopy.entity.file.ProtectionStatus;
import ru.soune.nocopy.exception.DuplicateImageException;
import ru.soune.nocopy.exception.FileEntityNotFoundException;
import ru.soune.nocopy.repository.FileEntityRepository;
import ru.soune.nocopy.repository.ImageHashRepository;
import ru.soune.nocopy.repository.SimilarImageProjection;
import ru.soune.nocopy.service.FileSimilarityService;
import ru.soune.nocopy.service.ImageHashService;
@@ -38,6 +39,8 @@ public class FileEntityService {
private final FileSimilarityService fileSimilarityService;
private final ImageHashRepository imageHashRepository;
@Transactional(noRollbackFor = DuplicateImageException.class)
public FileEntity createFromUploadSession(FileUploadSession session, String checksum) {
log.info("Creating FileEntity for upload session: {}", session.getUploadId());
@@ -185,27 +188,45 @@ public class FileEntityService {
}
@Transactional
public void markAsDeleted(FileEntity fileEntity) {
public FileEntity markAsDeleted(FileEntity fileEntity) throws IOException {
fileEntity.setStatus(FileStatus.DELETED);
fileEntity.setUpdatedAt(LocalDateTime.now());
fileEntity.setProtectionStatus(ProtectionStatus.NOT_PROTECTED);
Path path = Paths.get(fileEntity.getProtectedFilePath());
Files.deleteIfExists(path);
fileEntity.setProtectedFilePath("");
return fileEntityRepository.save(fileEntity);
}
public void softDeleteFileWithHash(FileEntity fileEntity) throws IOException {
if (fileEntity.getImageHash() != null) {
fileEntity.setImageHash(null);
}
fileEntity.setStatus(FileStatus.DELETED);
fileEntity.setUpdatedAt(LocalDateTime.now());
fileEntity.setProtectionStatus(ProtectionStatus.NOT_PROTECTED);
Path path = Paths.get(fileEntity.getProtectedFilePath());
Files.deleteIfExists(path);
fileEntity.setProtectedFilePath("");
fileEntityRepository.save(fileEntity);
}
@Transactional
public boolean deleteFromDisk(FileEntity fileEntity) throws IOException {
public void deleteFromDisk(FileEntity fileEntity) throws IOException {
Path path = Paths.get(fileEntity.getFilePath());
if (!Files.exists(path)) {
return true;
return;
}
Files.delete(path);
// markAsDeleted(fileEntity);
fileEntityRepository.delete(fileEntity);
return true;
}
@Transactional(readOnly = true)
@@ -1,4 +1,4 @@
package ru.soune.nocopy.service;
package ru.soune.nocopy.service.search;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;