2025-12-18 01:13:19 +07:00
|
|
|
package ru.soune.nocopy.handler;
|
|
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2026-03-27 13:37:37 +07:00
|
|
|
import org.springframework.data.domain.Page;
|
2026-04-13 17:16:32 +07:00
|
|
|
import org.springframework.data.domain.PageRequest;
|
|
|
|
|
import org.springframework.data.domain.Pageable;
|
|
|
|
|
import org.springframework.data.domain.Sort;
|
2025-12-18 01:13:19 +07:00
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
import ru.soune.nocopy.dto.*;
|
|
|
|
|
import ru.soune.nocopy.dto.file.*;
|
2026-03-27 13:37:37 +07:00
|
|
|
import ru.soune.nocopy.entity.file.FileAppeal;
|
2025-12-26 16:23:17 +07:00
|
|
|
import ru.soune.nocopy.entity.file.FileEntity;
|
|
|
|
|
import ru.soune.nocopy.entity.file.FileStatus;
|
2026-01-28 21:18:42 +07:00
|
|
|
import ru.soune.nocopy.entity.file.ProtectionStatus;
|
2026-03-27 13:37:37 +07:00
|
|
|
import ru.soune.nocopy.entity.file.moderation.ModerationLog;
|
2026-03-27 14:20:09 +07:00
|
|
|
import ru.soune.nocopy.exception.*;
|
2026-03-27 13:37:37 +07:00
|
|
|
import ru.soune.nocopy.repository.FileAppealRepository;
|
2025-12-26 16:23:17 +07:00
|
|
|
import ru.soune.nocopy.repository.FileEntityRepository;
|
2026-03-27 13:37:37 +07:00
|
|
|
import ru.soune.nocopy.repository.ModerationLogRepository;
|
|
|
|
|
import ru.soune.nocopy.service.file.moderation.ModerationService;
|
2026-01-21 12:02:38 +07:00
|
|
|
import ru.soune.nocopy.service.register.AuthService;
|
2025-12-18 01:13:19 +07:00
|
|
|
import ru.soune.nocopy.service.file.FileEntityService;
|
2026-01-06 12:50:39 +07:00
|
|
|
import ru.soune.nocopy.service.file.FileStatsService;
|
2025-12-18 01:13:19 +07:00
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
import java.time.LocalDate;
|
2026-03-19 18:03:44 +07:00
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.stream.Collectors;
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
@Slf4j
|
|
|
|
|
@Component
|
|
|
|
|
@RequiredArgsConstructor
|
|
|
|
|
public class FileEntityHandler implements RequestHandler {
|
2026-01-06 12:50:39 +07:00
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private final FileEntityService fileEntityService;
|
2025-12-26 16:23:17 +07:00
|
|
|
|
2026-01-05 16:26:46 +07:00
|
|
|
private final AuthService authService;
|
2026-01-06 12:50:39 +07:00
|
|
|
|
|
|
|
|
private final FileStatsService fileStatsService;
|
2025-12-26 16:23:17 +07:00
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private final ObjectMapper objectMapper;
|
|
|
|
|
|
2025-12-26 16:23:17 +07:00
|
|
|
private final FileEntityRepository fileEntityRepository;
|
|
|
|
|
|
2026-03-27 13:37:37 +07:00
|
|
|
private final ModerationService moderationService;
|
|
|
|
|
|
|
|
|
|
private final FileAppealRepository fileAppealRepository;
|
|
|
|
|
|
|
|
|
|
private final ModerationLogRepository moderationLogRepository;
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
@Override
|
|
|
|
|
public BaseResponse handle(BaseRequest request) {
|
|
|
|
|
try {
|
|
|
|
|
FileEntityRequest fileRequest = objectMapper.convertValue(
|
|
|
|
|
request.getMessageBody(), FileEntityRequest.class);
|
|
|
|
|
|
|
|
|
|
String action = fileRequest.getAction();
|
|
|
|
|
|
|
|
|
|
switch (action) {
|
2025-12-24 17:26:13 +07:00
|
|
|
case "file_info":
|
2025-12-18 01:13:19 +07:00
|
|
|
return handleGetFileInfo(request, fileRequest);
|
2026-01-06 12:50:39 +07:00
|
|
|
case "user_files_info":
|
|
|
|
|
return handleGetFilesUserInfo(request, fileRequest);
|
2025-12-24 17:26:13 +07:00
|
|
|
case "file_by_session":
|
2025-12-18 01:13:19 +07:00
|
|
|
return handleGetFileBySession(request, fileRequest);
|
2025-12-24 17:26:13 +07:00
|
|
|
case "user_files":
|
2025-12-18 01:13:19 +07:00
|
|
|
return handleGetUserFiles(request, fileRequest);
|
|
|
|
|
case "search_files":
|
|
|
|
|
return handleSearchFiles(request, fileRequest);
|
2025-12-24 17:26:13 +07:00
|
|
|
case "storage_usage":
|
2025-12-18 01:13:19 +07:00
|
|
|
return handleGetStorageUsage(request, fileRequest);
|
2026-01-28 21:18:42 +07:00
|
|
|
case "check_protected":
|
|
|
|
|
return handleProtectFile(request, fileRequest);
|
2025-12-18 01:13:19 +07:00
|
|
|
case "delete_file":
|
|
|
|
|
return handleDeleteFile(request, fileRequest);
|
2026-03-27 13:37:37 +07:00
|
|
|
case "change_file_status":
|
|
|
|
|
return handleChangeStatus(request, fileRequest);
|
|
|
|
|
case "moderate_file":
|
|
|
|
|
return handleModerateFile(request, fileRequest);
|
|
|
|
|
case "submit_appeal":
|
|
|
|
|
return handleSubmitAppeal(request, fileRequest);
|
|
|
|
|
case "review_appeal":
|
|
|
|
|
return handleReviewAppeal(request, fileRequest);
|
|
|
|
|
case "user_appeals":
|
|
|
|
|
return handleGetUserAppeals(request, fileRequest);
|
|
|
|
|
case "files_for_moderation":
|
|
|
|
|
return handleGetFilesForModeration(request, fileRequest);
|
2025-12-18 01:13:19 +07:00
|
|
|
default:
|
|
|
|
|
ActionResponse response = ActionResponse.builder()
|
|
|
|
|
.action(action)
|
|
|
|
|
.availableActions(Arrays.asList(
|
2025-12-24 17:26:13 +07:00
|
|
|
"file_info", "file_by_session", "user_files",
|
2026-01-09 23:05:37 +07:00
|
|
|
"search_files", "storage_usage", "delete_file",
|
|
|
|
|
"user_files_info"))
|
2025-12-18 01:13:19 +07:00
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_ACTION.getCode(),
|
|
|
|
|
"Invalid action: " + action,
|
|
|
|
|
response);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error in FileEntityHandler", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Handler error: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 12:50:39 +07:00
|
|
|
private BaseResponse handleGetFilesUserInfo(BaseRequest request, FileEntityRequest fileRequest) {
|
2026-01-09 22:55:06 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2026-01-06 12:50:39 +07:00
|
|
|
FileInfoUserResponse userFileStats = fileStatsService.getUserFileStats(userId);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
userFileStats);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private BaseResponse handleGetFileInfo(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-18 14:40:27 +07:00
|
|
|
FileEntityResponse fileInfo = fileEntityService.getById(fileRequest.getFileId(), request.getVersion());
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
if (!fileInfo.getUserId().equals(userId)) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Access denied",
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
fileInfo);
|
|
|
|
|
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting file info", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to get file info: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetFileBySession(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-18 14:40:27 +07:00
|
|
|
FileEntityResponse fileInfo = fileEntityService.getByUploadSessionId(fileRequest.getUploadSessionId(),
|
|
|
|
|
request.getVersion());
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
if (!fileInfo.getUserId().equals(userId)) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Access denied",
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
fileInfo);
|
|
|
|
|
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting file by session", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to get file: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetUserFiles(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-18 01:13:19 +07:00
|
|
|
int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
|
|
|
|
|
2025-12-18 14:40:27 +07:00
|
|
|
FileResponse files = fileEntityService.getUserFiles(userId, page, pageSize, request.getVersion());
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
files);
|
|
|
|
|
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting user files", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to get files: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 13:37:37 +07:00
|
|
|
private BaseResponse handleChangeStatus(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
FileStatus newStatus = fileRequest.getFileStatus();
|
2026-03-27 17:31:06 +07:00
|
|
|
String fileId = fileRequest.getFileId();
|
|
|
|
|
|
2026-03-27 13:37:37 +07:00
|
|
|
try {
|
|
|
|
|
fileEntityService.changeFileStatus(newStatus ,fileRequest.getFileId());
|
|
|
|
|
} catch (FileEntityNotFoundException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_NOT_FOUND.getCode(),
|
|
|
|
|
MessageCode.FILE_NOT_FOUND.getDescription(),
|
2026-03-27 19:08:15 +07:00
|
|
|
FileEntityResponse.builder().id(fileId).build());
|
2026-03-27 13:37:37 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
2026-04-04 15:31:51 +07:00
|
|
|
Map.of("file_status", newStatus, "file_id", fileId));
|
2026-03-27 13:37:37 +07:00
|
|
|
}
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private BaseResponse handleSearchFiles(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-18 01:13:19 +07:00
|
|
|
int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
2026-04-13 17:30:32 +07:00
|
|
|
String sortBy = fileRequest.getSortBy() != null ? fileRequest.getSortBy() : "createdAt";
|
2026-04-13 17:54:46 +07:00
|
|
|
String sortOrder = fileRequest.getSortOrder().equalsIgnoreCase("desc") ? "desc" :
|
|
|
|
|
"asc";
|
2026-04-13 17:16:32 +07:00
|
|
|
Sort sort = Sort.by(fileRequest.getSortOrder().equalsIgnoreCase("desc") ? Sort.Direction.DESC :
|
|
|
|
|
Sort.Direction.ASC, sortBy);
|
|
|
|
|
Pageable pageable = PageRequest.of(page, pageSize, sort);
|
|
|
|
|
FileResponse userFiles = fileEntityService.getUserFiles(userId, pageable, request.getVersion());
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
FileListResponse response = FileListResponse.builder()
|
2026-04-13 17:16:32 +07:00
|
|
|
.files(userFiles.getFiles())
|
|
|
|
|
.totalCount(userFiles.getTotalCount())
|
|
|
|
|
.totalSize(userFiles.getTotalSize())
|
|
|
|
|
.formattedTotalSize(fileEntityService.formatFileSize(userFiles.getTotalSize()))
|
2025-12-18 01:13:19 +07:00
|
|
|
.page(page)
|
|
|
|
|
.pageSize(pageSize)
|
2026-03-19 18:03:44 +07:00
|
|
|
.sortBy(sortBy)
|
2026-04-13 17:54:46 +07:00
|
|
|
.sortOrder(sortOrder)
|
2025-12-18 01:13:19 +07:00
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
2026-03-19 18:03:44 +07:00
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
} catch (NotFoundAuthToken e) {
|
2026-03-19 18:03:44 +07:00
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
2025-12-26 13:52:53 +07:00
|
|
|
"Authentication required", null);
|
2025-12-18 01:13:19 +07:00
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error searching files", e);
|
2026-03-19 18:03:44 +07:00
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
2025-12-26 13:52:53 +07:00
|
|
|
"Failed to search files: " + e.getMessage(), null);
|
2025-12-18 01:13:19 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 17:16:32 +07:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* private BaseResponse handleSearchFiles(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
* try {
|
|
|
|
|
* Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
|
|
|
|
* int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
* int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
|
|
|
|
*
|
|
|
|
|
* String sortBy = fileRequest.getSortBy() != null ? fileRequest.getSortBy() : "fileName";
|
|
|
|
|
* SortOrder sortOrder = SortOrder.fromString(fileRequest.getSortOrder());
|
|
|
|
|
*
|
|
|
|
|
* FileResponse allFiles = fileEntityService.getUserFiles(userId, 1, 1000, request.getVersion());
|
|
|
|
|
*
|
|
|
|
|
* String searchQuery = fileRequest.getQuery() != null ? fileRequest.getQuery().toLowerCase().trim() : "";
|
|
|
|
|
* String[] searchTerms = searchQuery.split("\\s+");
|
|
|
|
|
* String filterType = fileRequest.getType();
|
|
|
|
|
* String dateFilter = fileRequest.getDateFilter();
|
|
|
|
|
*
|
|
|
|
|
* List<FileEntityResponse> filteredFiles = allFiles.getFiles().stream()
|
|
|
|
|
* .filter(f -> matchesSearch(f, searchTerms, searchQuery, filterType))
|
|
|
|
|
* .filter(f -> matchesDateFilter(f, dateFilter))
|
|
|
|
|
* .collect(Collectors.toList());
|
|
|
|
|
*
|
|
|
|
|
* Comparator<FileEntityResponse> comparator = getComparator(sortBy, sortOrder);
|
|
|
|
|
* filteredFiles.sort(comparator);
|
|
|
|
|
*
|
|
|
|
|
* int start = (page - 1) * pageSize;
|
|
|
|
|
* int end = Math.min(start + pageSize, filteredFiles.size());
|
|
|
|
|
*
|
|
|
|
|
* if (start >= filteredFiles.size()) {
|
|
|
|
|
* return createEmptyResponse(request, page, pageSize, sortBy, sortOrder.getValue());
|
|
|
|
|
* }
|
|
|
|
|
*
|
|
|
|
|
* List<FileEntityResponse> paginatedFiles = filteredFiles.subList(start, end);
|
|
|
|
|
* long totalSize = paginatedFiles.stream()
|
|
|
|
|
* .mapToLong(FileEntityResponse::getFileSize)
|
|
|
|
|
* .sum();
|
|
|
|
|
*
|
|
|
|
|
* FileListResponse response = FileListResponse.builder()
|
|
|
|
|
* .files(paginatedFiles)
|
|
|
|
|
* .totalCount(filteredFiles.size())
|
|
|
|
|
* .totalSize(totalSize)
|
|
|
|
|
* .formattedTotalSize(fileEntityService.formatFileSize(totalSize))
|
|
|
|
|
* .page(page)
|
|
|
|
|
* .pageSize(pageSize)
|
|
|
|
|
* .sortBy(sortBy)
|
|
|
|
|
* .sortOrder(sortOrder.getValue())
|
|
|
|
|
* .build();
|
|
|
|
|
*
|
|
|
|
|
* return new BaseResponse(request.getMsgId(),
|
|
|
|
|
* MessageCode.SUCCESS.getCode(),
|
|
|
|
|
* MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
* response);
|
|
|
|
|
*
|
|
|
|
|
* } catch (NotFoundAuthToken e) {
|
|
|
|
|
* return new BaseResponse(request.getMsgId(),
|
|
|
|
|
* MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
* "Authentication required", null);
|
|
|
|
|
* } catch (Exception e) {
|
|
|
|
|
* log.error("Error searching files", e);
|
|
|
|
|
* return new BaseResponse(request.getMsgId(),
|
|
|
|
|
* MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
* "Failed to search files: " + e.getMessage(), null);
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
private boolean matchesDateFilter(FileEntityResponse file, String dateFilter) {
|
|
|
|
|
if (dateFilter == null || dateFilter.isEmpty()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LocalDate fileDate = file.getCreatedAt().toLocalDate();
|
|
|
|
|
LocalDate now = LocalDate.now();
|
|
|
|
|
|
|
|
|
|
switch (dateFilter.toLowerCase()) {
|
|
|
|
|
case "today":
|
|
|
|
|
return fileDate.equals(now);
|
|
|
|
|
case "week":
|
|
|
|
|
return fileDate.isAfter(now.minusWeeks(1)) && !fileDate.isAfter(now);
|
|
|
|
|
case "month":
|
|
|
|
|
return fileDate.isAfter(now.minusMonths(1)) && !fileDate.isAfter(now);
|
|
|
|
|
default:
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean matchesSearch(FileEntityResponse file, String[] searchTerms, String fullQuery, String type) {
|
2026-03-19 18:03:44 +07:00
|
|
|
String fileName = getSafeString(file.getFileName());
|
|
|
|
|
String originalFileName = getSafeString(file.getOriginalFileName());
|
2026-03-20 12:59:03 +07:00
|
|
|
String mimeType = getSafeString(file.getMimeType());
|
2026-03-19 18:03:44 +07:00
|
|
|
String fileFormat = getSafeString(file.getFileFormat());
|
|
|
|
|
String fullFileName = fileName + " " + originalFileName;
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
boolean matchesType = true;
|
|
|
|
|
if (type != null && !type.isEmpty()) {
|
|
|
|
|
matchesType = matchesMimeType(mimeType, type);
|
2026-03-19 18:03:44 +07:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
if (!matchesType) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2026-03-19 18:03:44 +07:00
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
if (fullQuery != null && !fullQuery.isEmpty()) {
|
|
|
|
|
if (fullFileName.toLowerCase().contains(fullQuery)) {
|
2026-03-19 18:03:44 +07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
for (String term : searchTerms) {
|
|
|
|
|
if (term.length() < 2) continue;
|
|
|
|
|
if (fullFileName.toLowerCase().contains(term)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-19 18:03:44 +07:00
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
if (fileFormat.toLowerCase().contains(fullQuery)) {
|
2026-03-19 18:03:44 +07:00
|
|
|
return true;
|
|
|
|
|
}
|
2026-03-20 12:59:03 +07:00
|
|
|
|
|
|
|
|
if (mimeType.toLowerCase().contains(fullQuery)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fileFormat.isEmpty() && !fileName.toLowerCase().endsWith("." + fileFormat.toLowerCase())) {
|
|
|
|
|
String fileNameWithExtension = fileName + "." + fileFormat;
|
|
|
|
|
if (fileNameWithExtension.toLowerCase().contains(fullQuery)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2026-03-19 18:03:44 +07:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean matchesMimeType(String mimeType, String filterType) {
|
|
|
|
|
if (filterType == null || filterType.isEmpty()) return true;
|
|
|
|
|
|
|
|
|
|
String mimeTypeLower = mimeType.toLowerCase();
|
|
|
|
|
String filterTypeLower = filterType.toLowerCase().trim();
|
|
|
|
|
|
|
|
|
|
return mimeTypeLower.equals(filterTypeLower);
|
2026-03-19 18:03:44 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getSafeString(String value) {
|
|
|
|
|
return value != null ? value : "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Comparator<FileEntityResponse> getComparator(String sortBy, SortOrder sortOrder) {
|
|
|
|
|
Comparator<FileEntityResponse> comparator;
|
|
|
|
|
|
|
|
|
|
switch (sortBy) {
|
|
|
|
|
case "fileSize":
|
|
|
|
|
comparator = Comparator.comparingLong(
|
|
|
|
|
FileEntityResponse::getFileSize
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
2026-03-20 12:59:03 +07:00
|
|
|
case "fileType":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
FileEntityResponse::getMimeType);
|
|
|
|
|
break;
|
|
|
|
|
|
2026-03-19 18:03:44 +07:00
|
|
|
case "createdAt":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
FileEntityResponse::getCreatedAt,
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "updatedAt":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
FileEntityResponse::getUpdatedAt,
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "fileName":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
f -> getSafeString(f.getFileName()).toLowerCase(),
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "protectStatus":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
f -> getSafeString(f.getProtectStatus()).toLowerCase(),
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "supportId":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
FileEntityResponse::getSupportId,
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
2026-04-13 15:35:49 +07:00
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
case "monitoring":
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
FileEntityResponse::getMonitoring,
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
2026-03-19 18:03:44 +07:00
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
comparator = Comparator.comparing(
|
|
|
|
|
f -> getSafeString(f.getFileName()).toLowerCase(),
|
|
|
|
|
Comparator.nullsLast(Comparator.naturalOrder())
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sortOrder == SortOrder.DESC ? comparator.reversed() : comparator;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse createEmptyResponse(BaseRequest request, int page, int pageSize,
|
|
|
|
|
String sortBy, String sortOrder) {
|
|
|
|
|
FileListResponse emptyResponse = FileListResponse.builder()
|
|
|
|
|
.files(Collections.emptyList())
|
|
|
|
|
.totalCount(0)
|
|
|
|
|
.totalSize(0L)
|
|
|
|
|
.formattedTotalSize("0 B")
|
|
|
|
|
.page(page)
|
|
|
|
|
.pageSize(pageSize)
|
|
|
|
|
.sortBy(sortBy)
|
|
|
|
|
.sortOrder(sortOrder)
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
emptyResponse);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetUserFilesWithSort(BaseRequest request, FileEntityRequest fileRequest,
|
|
|
|
|
String sortBy, SortOrder sortOrder) {
|
|
|
|
|
try {
|
|
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
|
|
|
|
int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
|
|
|
|
|
|
|
|
|
FileResponse allFiles = fileEntityService.getUserFiles(userId, 1, 1000, request.getVersion());
|
|
|
|
|
|
|
|
|
|
List<FileEntityResponse> files = new ArrayList<>(allFiles.getFiles());
|
|
|
|
|
|
|
|
|
|
Comparator<FileEntityResponse> comparator = getComparator(sortBy, sortOrder);
|
|
|
|
|
files.sort(comparator);
|
|
|
|
|
|
|
|
|
|
int start = (page - 1) * pageSize;
|
|
|
|
|
int end = Math.min(start + pageSize, files.size());
|
|
|
|
|
|
|
|
|
|
if (start >= files.size()) {
|
|
|
|
|
return createEmptyResponse(request, page, pageSize, sortBy, sortOrder.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<FileEntityResponse> paginatedFiles = files.subList(start, end);
|
|
|
|
|
long totalSize = paginatedFiles.stream()
|
|
|
|
|
.mapToLong(FileEntityResponse::getFileSize)
|
|
|
|
|
.sum();
|
|
|
|
|
|
|
|
|
|
FileListResponse response = FileListResponse.builder()
|
|
|
|
|
.files(paginatedFiles)
|
|
|
|
|
.totalCount(files.size())
|
|
|
|
|
.totalSize(totalSize)
|
|
|
|
|
.formattedTotalSize(fileEntityService.formatFileSize(totalSize))
|
|
|
|
|
.page(page)
|
|
|
|
|
.pageSize(pageSize)
|
|
|
|
|
.sortBy(sortBy)
|
|
|
|
|
.sortOrder(sortOrder.getValue())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
|
|
|
|
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required", null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting user files with sort", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to get files: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private BaseResponse handleGetStorageUsage(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-18 01:13:19 +07:00
|
|
|
long usage = fileEntityService.getUserStorageUsed(userId);
|
|
|
|
|
|
|
|
|
|
StorageUsageResponse response = StorageUsageResponse.builder()
|
|
|
|
|
.userId(userId)
|
|
|
|
|
.storageUsed(usage)
|
|
|
|
|
.formattedStorageUsed(formatFileSize(usage))
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
|
|
|
|
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting storage usage", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to get storage usage: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-28 21:18:42 +07:00
|
|
|
private BaseResponse handleProtectFile(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
String fileId = fileRequest.getFileId();
|
|
|
|
|
Optional<FileEntity> optionalFileEntity = fileEntityRepository.findById(fileId);
|
|
|
|
|
|
|
|
|
|
if (optionalFileEntity.isEmpty()) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_NOT_FOUND.getCode(),
|
|
|
|
|
"File not found exception: " + fileRequest.getFileId(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileEntity fileEntity = optionalFileEntity.get();
|
|
|
|
|
ProtectionStatus protectionStatus = fileEntity.getProtectionStatus();
|
|
|
|
|
|
|
|
|
|
Integer code = protectionStatus == ProtectionStatus.PROTECTED ? MessageCode.FILE_IS_PROTECTED.getCode():
|
|
|
|
|
MessageCode.FILE_IS_NOT_PROTECTED.getCode();
|
|
|
|
|
String message = protectionStatus == ProtectionStatus.PROTECTED ? MessageCode.FILE_IS_PROTECTED.getDescription():
|
|
|
|
|
MessageCode.FILE_IS_NOT_PROTECTED.getDescription();
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(), code, message, fileEntityService.getById(fileId,
|
|
|
|
|
request.getVersion()));
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private BaseResponse handleDeleteFile(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
2026-01-05 16:26:46 +07:00
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
2025-12-26 16:23:17 +07:00
|
|
|
String fileId = fileRequest.getFileId();
|
|
|
|
|
FileEntityResponse fileInfo = fileEntityService.getById(fileId, request.getVersion());
|
|
|
|
|
DeleteFileResponse response;
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
if (!fileInfo.getUserId().equals(userId)) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Access denied",
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-26 16:23:17 +07:00
|
|
|
FileEntity fileEntity = fileEntityRepository.findById(fileId)
|
|
|
|
|
.orElseThrow(() -> new FileEntityNotFoundException(fileId));
|
2026-01-27 08:09:54 +07:00
|
|
|
int fullDelete = fileRequest.getFullDelete() == null ? 0 : fileRequest.getFullDelete();
|
2025-12-18 01:13:19 +07:00
|
|
|
|
2026-01-27 08:09:54 +07:00
|
|
|
if (fileEntity.getStatus().equals(FileStatus.DELETED) || fullDelete == 1) {
|
2025-12-26 16:23:17 +07:00
|
|
|
fileEntityService.deleteFromDisk(fileEntity);
|
|
|
|
|
response = DeleteFileResponse.builder()
|
|
|
|
|
.fileId(fileRequest.getFileId())
|
|
|
|
|
.message("File deleted from disk")
|
|
|
|
|
.build();
|
|
|
|
|
} else {
|
2026-01-27 08:09:54 +07:00
|
|
|
fileEntityService.softDeleteFileWithHash(fileEntity);
|
|
|
|
|
|
2025-12-26 16:23:17 +07:00
|
|
|
response = DeleteFileResponse.builder()
|
|
|
|
|
.fileId(fileRequest.getFileId())
|
|
|
|
|
.message("File marked as deleted")
|
|
|
|
|
.build();
|
|
|
|
|
}
|
2025-12-18 01:13:19 +07:00
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
"File marked as deleted",
|
|
|
|
|
response);
|
|
|
|
|
} catch (NotFoundAuthToken e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error deleting file", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_UPLOAD_ERROR.getCode(),
|
|
|
|
|
"Failed to delete file: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-27 13:37:37 +07:00
|
|
|
private BaseResponse handleModerateFile(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
//TODO добавить проверку на админа
|
|
|
|
|
// Long moderatorId = authService.useAdminAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
ModerationActionRequest moderationRequest = ModerationActionRequest.builder()
|
|
|
|
|
.fileId(fileRequest.getFileId())
|
|
|
|
|
.newStatus(fileRequest.getFileStatus())
|
|
|
|
|
.comment(fileRequest.getComment())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
//TODO set moderator ID
|
|
|
|
|
moderationService.moderateFile(moderationRequest, 0L);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
2026-03-27 17:31:06 +07:00
|
|
|
MessageCode.SUCCESS_MODERATION.getCode(),
|
|
|
|
|
MessageCode.SUCCESS_MODERATION.getDescription(),
|
2026-03-27 19:08:15 +07:00
|
|
|
FileEntityResponse.builder().id(fileRequest.getFileId()).build());
|
2026-03-27 13:37:37 +07:00
|
|
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
2026-03-27 17:31:06 +07:00
|
|
|
MessageCode.ACCESS_DENIED.getDescription(),
|
2026-03-27 19:08:15 +07:00
|
|
|
FileEntityResponse.builder().id(fileRequest.getFileId()).build());
|
2026-03-27 17:31:06 +07:00
|
|
|
} catch (FileEntityNotFoundException e) {
|
2026-03-27 13:37:37 +07:00
|
|
|
return new BaseResponse(request.getMsgId(),
|
2026-03-27 17:31:06 +07:00
|
|
|
MessageCode.FILE_NOT_FOUND.getCode(),
|
|
|
|
|
MessageCode.FILE_NOT_FOUND.getDescription(),
|
|
|
|
|
FileEntityResponse.builder()
|
2026-03-27 19:08:15 +07:00
|
|
|
.id(fileRequest.getFileId()).build());
|
2026-03-27 17:31:06 +07:00
|
|
|
} catch (IllegalStateException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ILLEGAL_STATE.getCode(),
|
|
|
|
|
MessageCode.ILLEGAL_STATE.getDescription(),
|
|
|
|
|
FileEntityResponse.builder()
|
2026-03-27 19:08:15 +07:00
|
|
|
.status(fileRequest.getFileStatus()).build());
|
2026-03-27 13:37:37 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleSubmitAppeal(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
AppealRequest appealRequest = AppealRequest.builder()
|
|
|
|
|
.fileId(fileRequest.getFileId())
|
|
|
|
|
.appealReason(fileRequest.getAppealReason())
|
|
|
|
|
.additionalInfo(fileRequest.getAdditionalInfo())
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
AppealResponse response = moderationService.submitAppeal(appealRequest, userId);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
"Appeal submitted successfully",
|
|
|
|
|
response);
|
|
|
|
|
} catch (InvalidAppealException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"Failed to submit appeal: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleReviewAppeal(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
// TODO
|
|
|
|
|
// Long moderatorId = authService.useAdminAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
String appealId = fileRequest.getAppealId();
|
|
|
|
|
Boolean approve = fileRequest.getApprove();
|
|
|
|
|
String comment = fileRequest.getComment();
|
|
|
|
|
|
|
|
|
|
if (appealId == null || approve == null) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"appealId and approve are required",
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
//TODO
|
|
|
|
|
moderationService.reviewAppeal(appealId, approve, comment, 0L);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
"Appeal reviewed successfully",
|
|
|
|
|
Map.of(
|
|
|
|
|
"appealId", appealId,
|
|
|
|
|
"approved", approve,
|
|
|
|
|
"comment", comment
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Admin access required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (IllegalStateException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error reviewing appeal", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"Failed to review appeal: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetUserAppeals(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
|
|
|
|
|
|
|
|
|
Page<AppealResponse> appeals = moderationService.getUserAppeals(userId, page - 1, pageSize);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> response = Map.of(
|
|
|
|
|
"appeals", appeals.getContent(),
|
|
|
|
|
"totalCount", appeals.getTotalElements(),
|
|
|
|
|
"totalPages", appeals.getTotalPages(),
|
|
|
|
|
"currentPage", page,
|
|
|
|
|
"pageSize", pageSize);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
|
|
|
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_TOKEN.getCode(),
|
|
|
|
|
"Authentication required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting user appeals", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"Failed to get appeals: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetFilesForModeration(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
//TODO
|
|
|
|
|
// authService.useAdminAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1;
|
|
|
|
|
int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20;
|
|
|
|
|
|
|
|
|
|
Page<FileEntity> files = moderationService.getFilesForModeration(page - 1, pageSize);
|
|
|
|
|
|
|
|
|
|
List<Map<String, Object>> filesWithInfo = files.getContent().stream()
|
|
|
|
|
.map(file -> {
|
|
|
|
|
FileModerationInfo info = moderationService.getFileModerationInfo(file.getId());
|
2026-03-27 15:31:45 +07:00
|
|
|
|
|
|
|
|
Map<String, Object> fileMap = new HashMap<>();
|
|
|
|
|
fileMap.put("fileId", file.getId());
|
|
|
|
|
fileMap.put("fileName", file.getOriginalFileName());
|
|
|
|
|
fileMap.put("userId", file.getUserId());
|
|
|
|
|
fileMap.put("status", file.getStatus() != null ? file.getStatus().name() : null);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> moderationInfoMap = new HashMap<>();
|
|
|
|
|
moderationInfoMap.put("hasActiveAppeal", info != null && info.getHasActiveAppeal());
|
|
|
|
|
|
|
|
|
|
if (info != null && info.getActiveAppeal() != null) {
|
|
|
|
|
Map<String, Object> appealInfoMap = new HashMap<>();
|
|
|
|
|
appealInfoMap.put("appealId", info.getActiveAppeal().getAppealId());
|
|
|
|
|
appealInfoMap.put("status", info.getActiveAppeal().getStatus());
|
|
|
|
|
appealInfoMap.put("createdAt", info.getActiveAppeal().getCreatedAt());
|
|
|
|
|
moderationInfoMap.put("appealInfo", appealInfoMap);
|
|
|
|
|
} else {
|
|
|
|
|
moderationInfoMap.put("appealInfo", null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fileMap.put("moderationInfo", moderationInfoMap);
|
|
|
|
|
|
|
|
|
|
return fileMap;
|
2026-03-27 13:37:37 +07:00
|
|
|
})
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
Map<String, Object> response = Map.of(
|
|
|
|
|
"files", filesWithInfo,
|
|
|
|
|
"totalCount", files.getTotalElements(),
|
|
|
|
|
"totalPages", files.getTotalPages(),
|
|
|
|
|
"currentPage", page,
|
|
|
|
|
"pageSize", pageSize
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
|
|
|
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Admin access required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting files for moderation", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"Failed to get files: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BaseResponse handleGetFileModerationInfo(BaseRequest request, FileEntityRequest fileRequest) {
|
|
|
|
|
try {
|
|
|
|
|
// TODO
|
|
|
|
|
// authService.useAdminAuthToken(fileRequest.getToken());
|
|
|
|
|
|
|
|
|
|
String fileId = fileRequest.getFileId();
|
|
|
|
|
if (fileId == null) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"fileId is required",
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileModerationInfo moderationInfo = moderationService.getFileModerationInfo(fileId);
|
|
|
|
|
|
|
|
|
|
FileEntity file = fileEntityRepository.findById(fileId)
|
|
|
|
|
.orElseThrow(() -> new FileEntityNotFoundException(fileId));
|
|
|
|
|
|
|
|
|
|
Map<String, Object> fileInfoMap = new HashMap<>();
|
|
|
|
|
fileInfoMap.put("id", file.getId());
|
|
|
|
|
fileInfoMap.put("fileName", file.getOriginalFileName());
|
|
|
|
|
fileInfoMap.put("storedFileName", file.getStoredFileName());
|
|
|
|
|
fileInfoMap.put("fileSize", file.getFileSize());
|
|
|
|
|
fileInfoMap.put("formattedSize", fileEntityService.formatFileSize(file.getFileSize()));
|
|
|
|
|
fileInfoMap.put("mimeType", file.getMimeType());
|
|
|
|
|
fileInfoMap.put("fileExtension", file.getFileExtension());
|
|
|
|
|
fileInfoMap.put("checksum", file.getChecksum());
|
|
|
|
|
fileInfoMap.put("status", file.getStatus() != null ? file.getStatus().name() : null);
|
|
|
|
|
fileInfoMap.put("createdAt", file.getCreatedAt());
|
|
|
|
|
fileInfoMap.put("updatedAt", file.getUpdatedAt());
|
|
|
|
|
|
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
|
|
|
response.put("fileInfo", fileInfoMap);
|
|
|
|
|
response.put("moderationInfo", moderationInfo != null ? moderationInfo : new HashMap<>());
|
|
|
|
|
response.put("moderationHistory", getModerationHistory(fileId));
|
|
|
|
|
response.put("appeals", getFileAppeals(fileId));
|
|
|
|
|
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.SUCCESS.getCode(),
|
|
|
|
|
MessageCode.SUCCESS.getDescription(),
|
|
|
|
|
response);
|
|
|
|
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.ACCESS_DENIED.getCode(),
|
|
|
|
|
"Admin access required",
|
|
|
|
|
null);
|
|
|
|
|
} catch (FileEntityNotFoundException e) {
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.FILE_NOT_FOUND.getCode(),
|
|
|
|
|
e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("Error getting file moderation info", e);
|
|
|
|
|
return new BaseResponse(request.getMsgId(),
|
|
|
|
|
MessageCode.INVALID_FIELD.getCode(),
|
|
|
|
|
"Failed to get file info: " + e.getMessage(),
|
|
|
|
|
null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<Map<String, Object>> getModerationHistory(String fileId) {
|
|
|
|
|
List<ModerationLog> logs = moderationLogRepository.findByFileIdOrderByCreatedAtDesc(fileId);
|
|
|
|
|
if (logs == null || logs.isEmpty()) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return logs.stream()
|
|
|
|
|
.map(log -> {
|
|
|
|
|
Map<String, Object> logMap = new HashMap<>();
|
|
|
|
|
logMap.put("id", log.getId());
|
|
|
|
|
logMap.put("moderatorId", log.getModeratorId());
|
|
|
|
|
logMap.put("oldStatus", log.getOldStatus() != null ? log.getOldStatus().name() : null);
|
|
|
|
|
logMap.put("newStatus", log.getNewStatus() != null ? log.getNewStatus().name() : null);
|
|
|
|
|
logMap.put("reason", log.getReason());
|
|
|
|
|
logMap.put("comment", log.getComment());
|
|
|
|
|
logMap.put("createdAt", log.getCreatedAt());
|
|
|
|
|
return logMap;
|
|
|
|
|
})
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<Map<String, Object>> getFileAppeals(String fileId) {
|
|
|
|
|
List<FileAppeal> appeals = fileAppealRepository.findByFileId(fileId);
|
|
|
|
|
if (appeals == null || appeals.isEmpty()) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return appeals.stream()
|
|
|
|
|
.map(appeal -> {
|
|
|
|
|
Map<String, Object> appealMap = new HashMap<>();
|
|
|
|
|
appealMap.put("id", appeal.getId());
|
|
|
|
|
appealMap.put("userId", appeal.getUserId());
|
|
|
|
|
appealMap.put("appealReason", appeal.getAppealReason());
|
|
|
|
|
appealMap.put("additionalInfo", appeal.getAdditionalInfo());
|
|
|
|
|
appealMap.put("status", appeal.getStatus() != null ? appeal.getStatus().name() : null);
|
|
|
|
|
appealMap.put("adminComment", appeal.getAdminComment());
|
|
|
|
|
appealMap.put("moderatorId", appeal.getModeratorId());
|
|
|
|
|
appealMap.put("createdAt", appeal.getCreatedAt());
|
|
|
|
|
appealMap.put("resolvedAt", appeal.getResolvedAt());
|
|
|
|
|
return appealMap;
|
|
|
|
|
})
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-18 01:13:19 +07:00
|
|
|
private String formatFileSize(long size) {
|
|
|
|
|
if (size < 1024) return size + " B";
|
|
|
|
|
int exp = (int) (Math.log(size) / Math.log(1024));
|
|
|
|
|
String pre = "KMGTPE".charAt(exp-1) + "";
|
|
|
|
|
return String.format("%.1f %sB", size / Math.pow(1024, exp), pre);
|
|
|
|
|
}
|
|
|
|
|
}
|