@@ -27,6 +27,7 @@ import ru.soune.nocopy.entity.company.Company;
|
|||||||
import ru.soune.nocopy.entity.file.FileEntity;
|
import ru.soune.nocopy.entity.file.FileEntity;
|
||||||
import ru.soune.nocopy.entity.file.FileStatus;
|
import ru.soune.nocopy.entity.file.FileStatus;
|
||||||
import ru.soune.nocopy.entity.file.UploadStatus;
|
import ru.soune.nocopy.entity.file.UploadStatus;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
import ru.soune.nocopy.entity.user.AuthToken;
|
import ru.soune.nocopy.entity.user.AuthToken;
|
||||||
import ru.soune.nocopy.entity.user.User;
|
import ru.soune.nocopy.entity.user.User;
|
||||||
import ru.soune.nocopy.exception.*;
|
import ru.soune.nocopy.exception.*;
|
||||||
@@ -467,6 +468,16 @@ public class ApiController {
|
|||||||
errorData));
|
errorData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!entityResponse.getPermissions().get(PermissionType.DOWNLOAD)) {
|
||||||
|
Map<String, Object> errorData = new HashMap<>();
|
||||||
|
errorData.put("fileId", entityResponse.getId());
|
||||||
|
|
||||||
|
return ResponseEntity.ok().body(new BaseResponse(20004,
|
||||||
|
MessageCode.NOT_HAVE_DOWNLOAD_PERMISSION.getCode(),
|
||||||
|
MessageCode.NOT_HAVE_DOWNLOAD_PERMISSION.getDescription(),
|
||||||
|
errorData));
|
||||||
|
}
|
||||||
|
|
||||||
User fileUser = userRepository.findById(entityResponse.getUserId()).orElseThrow();
|
User fileUser = userRepository.findById(entityResponse.getUserId()).orElseThrow();
|
||||||
User user = userRepository.findById(userId).orElseThrow();
|
User user = userRepository.findById(userId).orElseThrow();
|
||||||
Company companyUser = user.getCompany();
|
Company companyUser = user.getCompany();
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ public enum MessageCode {
|
|||||||
USER_VERIFICATIONS_NOT_FOUND(4, "Verifications not found"),
|
USER_VERIFICATIONS_NOT_FOUND(4, "Verifications not found"),
|
||||||
COMPLAINT_OR_LAW_CASE_IN_WORK(2, "Complaint or lawcase in work"),
|
COMPLAINT_OR_LAW_CASE_IN_WORK(2, "Complaint or lawcase in work"),
|
||||||
NOT_VALID_STATUS(2, "Not valid status"),
|
NOT_VALID_STATUS(2, "Not valid status"),
|
||||||
|
PERMISSION_NOT_VALID(2, "Not valid permission"),
|
||||||
|
NOT_HAVE_DOWNLOAD_PERMISSION(2, "Not haver permission for download"),
|
||||||
ADMIN_USER_NOT_FOUND(4, "Verifications ,user or admin not found");
|
ADMIN_USER_NOT_FOUND(4, "Verifications ,user or admin not found");
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import ru.soune.nocopy.entity.file.FileStatus;
|
import ru.soune.nocopy.entity.file.FileStatus;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@@ -76,4 +78,7 @@ public class FileEntityRequest {
|
|||||||
|
|
||||||
@JsonProperty("search_query")
|
@JsonProperty("search_query")
|
||||||
private String searchQuery;
|
private String searchQuery;
|
||||||
|
|
||||||
|
@JsonProperty("permissions")
|
||||||
|
private Map<String, Boolean> permissions;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import ru.soune.nocopy.entity.file.FileStatus;
|
import ru.soune.nocopy.entity.file.FileStatus;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@@ -42,4 +44,5 @@ public class FileEntityResponse {
|
|||||||
private Integer checksCount;
|
private Integer checksCount;
|
||||||
private LocalDateTime fileUploadDate;
|
private LocalDateTime fileUploadDate;
|
||||||
private String monitoring;
|
private String monitoring;
|
||||||
|
private Map<PermissionType, Boolean> permissions;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ import lombok.*;
|
|||||||
import org.springframework.data.annotation.CreatedDate;
|
import org.springframework.data.annotation.CreatedDate;
|
||||||
import org.springframework.data.annotation.LastModifiedDate;
|
import org.springframework.data.annotation.LastModifiedDate;
|
||||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
import ru.soune.nocopy.entity.monitoring.FileMonitoringEntity;
|
import ru.soune.nocopy.entity.monitoring.FileMonitoringEntity;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@@ -92,6 +95,14 @@ public class FileEntity {
|
|||||||
@Column
|
@Column
|
||||||
private String newExtension;
|
private String newExtension;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable(name = "file_permissions",
|
||||||
|
joinColumns = @JoinColumn(name = "file_id"))
|
||||||
|
@Column(name = "allowed")
|
||||||
|
@MapKeyEnumerated(EnumType.STRING)
|
||||||
|
@MapKeyColumn(name = "permission_type")
|
||||||
|
private Map<PermissionType, Boolean> permissions = new HashMap<>();
|
||||||
|
|
||||||
@OneToOne(mappedBy = "file", cascade = CascadeType.ALL, orphanRemoval = true)
|
@OneToOne(mappedBy = "file", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private ImageHashEntity imageHash;
|
private ImageHashEntity imageHash;
|
||||||
@@ -113,6 +124,15 @@ public class FileEntity {
|
|||||||
if (this.createdAt == null) {
|
if (this.createdAt == null) {
|
||||||
this.createdAt = LocalDateTime.now();
|
this.createdAt = LocalDateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.permissions == null) {
|
||||||
|
this.permissions = new HashMap<>();
|
||||||
|
this.permissions.put(PermissionType.DOWNLOAD, true);
|
||||||
|
// this.permissions.put(PermissionType.VIEW, true);
|
||||||
|
// this.permissions.put(PermissionType.EDIT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.updatedAt = LocalDateTime.now();
|
this.updatedAt = LocalDateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,4 +144,29 @@ public class FileEntity {
|
|||||||
public static void initializeCounter(int maxId) {
|
public static void initializeCounter(int maxId) {
|
||||||
supportIdCounter = new AtomicInteger(maxId);
|
supportIdCounter = new AtomicInteger(maxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public boolean hasPermission(PermissionType type) {
|
||||||
|
return permissions.getOrDefault(type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public void setPermission(PermissionType type, boolean allowed) {
|
||||||
|
permissions.put(type, allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
public boolean canDownload() {
|
||||||
|
return hasPermission(PermissionType.DOWNLOAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Transient
|
||||||
|
// public boolean canView() {
|
||||||
|
// return hasPermission(PermissionType.VIEW);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Transient
|
||||||
|
// public boolean canEdit() {
|
||||||
|
// return hasPermission(PermissionType.EDIT);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package ru.soune.nocopy.entity.file.permission;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public enum PermissionType {
|
||||||
|
DOWNLOAD;
|
||||||
|
|
||||||
|
public static Set<String> getValidPermissionNames() {
|
||||||
|
return Arrays.stream(PermissionType.values())
|
||||||
|
.map(Enum::name)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<String> getInvalidPermissions(Map<String, Boolean> permissions) {
|
||||||
|
Set<String> validNames = getValidPermissionNames();
|
||||||
|
return permissions.keySet().stream()
|
||||||
|
.filter(key -> !validNames.contains(key))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean areAllValid(Map<String, Boolean> permissions) {
|
||||||
|
return getInvalidPermissions(permissions).isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,11 +13,13 @@ import ru.soune.nocopy.dto.*;
|
|||||||
import ru.soune.nocopy.dto.file.*;
|
import ru.soune.nocopy.dto.file.*;
|
||||||
import ru.soune.nocopy.entity.file.*;
|
import ru.soune.nocopy.entity.file.*;
|
||||||
import ru.soune.nocopy.entity.file.moderation.ModerationLog;
|
import ru.soune.nocopy.entity.file.moderation.ModerationLog;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
import ru.soune.nocopy.entity.monitoring.FileMonitoringEntity;
|
import ru.soune.nocopy.entity.monitoring.FileMonitoringEntity;
|
||||||
import ru.soune.nocopy.exception.*;
|
import ru.soune.nocopy.exception.*;
|
||||||
import ru.soune.nocopy.repository.*;
|
import ru.soune.nocopy.repository.*;
|
||||||
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
|
import ru.soune.nocopy.service.file.cloud.CloudStorageService;
|
||||||
import ru.soune.nocopy.service.file.moderation.ModerationService;
|
import ru.soune.nocopy.service.file.moderation.ModerationService;
|
||||||
|
import ru.soune.nocopy.service.file.permission.FileAccessService;
|
||||||
import ru.soune.nocopy.service.register.AuthService;
|
import ru.soune.nocopy.service.register.AuthService;
|
||||||
import ru.soune.nocopy.service.file.FileEntityService;
|
import ru.soune.nocopy.service.file.FileEntityService;
|
||||||
import ru.soune.nocopy.service.file.FileStatsService;
|
import ru.soune.nocopy.service.file.FileStatsService;
|
||||||
@@ -57,6 +59,8 @@ public class FileEntityHandler implements RequestHandler {
|
|||||||
|
|
||||||
private final ImageHashRepository imageHashRepository;
|
private final ImageHashRepository imageHashRepository;
|
||||||
|
|
||||||
|
private FileAccessService fileAccessService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseResponse handle(BaseRequest request) {
|
public BaseResponse handle(BaseRequest request) {
|
||||||
try {
|
try {
|
||||||
@@ -96,6 +100,8 @@ public class FileEntityHandler implements RequestHandler {
|
|||||||
return handleGetUserAppeals(request, fileRequest);
|
return handleGetUserAppeals(request, fileRequest);
|
||||||
case "files_for_moderation":
|
case "files_for_moderation":
|
||||||
return handleGetFilesForModeration(request, fileRequest);
|
return handleGetFilesForModeration(request, fileRequest);
|
||||||
|
case "change_permission":
|
||||||
|
return handleChangePermission(request, fileRequest);
|
||||||
default:
|
default:
|
||||||
ActionResponse response = ActionResponse.builder()
|
ActionResponse response = ActionResponse.builder()
|
||||||
.action(action)
|
.action(action)
|
||||||
@@ -160,6 +166,57 @@ public class FileEntityHandler implements RequestHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BaseResponse handleChangePermission(BaseRequest request, FileEntityRequest fileRequest) {
|
||||||
|
try {
|
||||||
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
||||||
|
FileEntityResponse fileInfo = fileEntityService.getById(fileRequest.getFileId(), request.getVersion());
|
||||||
|
|
||||||
|
if (!fileInfo.getUserId().equals(userId)) {
|
||||||
|
return new BaseResponse(request.getMsgId(),
|
||||||
|
MessageCode.ACCESS_DENIED.getCode(),
|
||||||
|
"Access denied",
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Boolean> permissions = fileRequest.getPermissions();
|
||||||
|
|
||||||
|
if (!PermissionType.areAllValid(permissions)) {
|
||||||
|
return new BaseResponse(request.getMsgId(),
|
||||||
|
MessageCode.PERMISSION_NOT_VALID.getCode(),
|
||||||
|
MessageCode.PERMISSION_NOT_VALID.getDescription(),
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, Boolean> entry: permissions.entrySet()) {
|
||||||
|
try {
|
||||||
|
fileAccessService.changePermission(fileInfo.getId(), PermissionType.valueOf(entry.getKey()),
|
||||||
|
entry.getValue());
|
||||||
|
} catch (FileEntityNotFoundException e) {
|
||||||
|
return new BaseResponse(request.getMsgId(),
|
||||||
|
MessageCode.FILE_NOT_FOUND.getCode(),
|
||||||
|
MessageCode.FILE_NOT_FOUND.getDescription(),
|
||||||
|
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) {
|
private BaseResponse handleGetFileBySession(BaseRequest request, FileEntityRequest fileRequest) {
|
||||||
try {
|
try {
|
||||||
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
Long userId = authService.useUserAuthToken(fileRequest.getToken());
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ public class FileEntityService {
|
|||||||
.fileUploadDate(fileEntity.getCreatedAt())
|
.fileUploadDate(fileEntity.getCreatedAt())
|
||||||
.protectedFilePath(fileEntity.getProtectedFilePath())
|
.protectedFilePath(fileEntity.getProtectedFilePath())
|
||||||
.thumbnailFileUrl(baseUrl + "/api/files/protected/" + fileEntity.getId() + "/thumbnail")
|
.thumbnailFileUrl(baseUrl + "/api/files/protected/" + fileEntity.getId() + "/thumbnail")
|
||||||
|
.permissions(fileEntity.getPermissions())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package ru.soune.nocopy.service.file.permission;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.soune.nocopy.entity.file.FileEntity;
|
||||||
|
import ru.soune.nocopy.entity.file.permission.PermissionType;
|
||||||
|
import ru.soune.nocopy.repository.FileEntityRepository;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FileAccessService {
|
||||||
|
|
||||||
|
private final FileEntityRepository fileEntityRepository;
|
||||||
|
|
||||||
|
public void changePermission(String fileId, PermissionType type, boolean allowed) throws FileNotFoundException {
|
||||||
|
FileEntity file = fileEntityRepository.findById(fileId)
|
||||||
|
.orElseThrow(() -> new FileNotFoundException(fileId));
|
||||||
|
file.setPermission(type, allowed);
|
||||||
|
|
||||||
|
fileEntityRepository.save(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user