-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
5696b28
commit ca0be9e
Showing
11 changed files
with
538 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
src/main/java/com/epam/aidial/core/controller/ResourceOperationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package com.epam.aidial.core.controller; | ||
|
||
import com.epam.aidial.core.Proxy; | ||
import com.epam.aidial.core.ProxyContext; | ||
import com.epam.aidial.core.data.MoveResourcesRequest; | ||
import com.epam.aidial.core.security.EncryptionService; | ||
import com.epam.aidial.core.service.LockService; | ||
import com.epam.aidial.core.service.ResourceOperationService; | ||
import com.epam.aidial.core.storage.BlobStorageUtil; | ||
import com.epam.aidial.core.storage.ResourceDescription; | ||
import com.epam.aidial.core.util.HttpException; | ||
import com.epam.aidial.core.util.HttpStatus; | ||
import com.epam.aidial.core.util.ProxyUtil; | ||
import io.vertx.core.Future; | ||
import io.vertx.core.Vertx; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
public class ResourceOperationController { | ||
|
||
private final ProxyContext context; | ||
private final Proxy proxy; | ||
private final Vertx vertx; | ||
private final EncryptionService encryptionService; | ||
private final ResourceOperationService resourceOperationService; | ||
private final LockService lockService; | ||
|
||
public ResourceOperationController(Proxy proxy, ProxyContext context) { | ||
this.context = context; | ||
this.proxy = proxy; | ||
this.vertx = proxy.getVertx(); | ||
this.encryptionService = proxy.getEncryptionService(); | ||
this.resourceOperationService = proxy.getResourceOperationService(); | ||
this.lockService = proxy.getLockService(); | ||
} | ||
|
||
public Future<?> move() { | ||
context.getRequest() | ||
.body() | ||
.compose(buffer -> { | ||
MoveResourcesRequest request; | ||
try { | ||
request = ProxyUtil.convertToObject(buffer, MoveResourcesRequest.class); | ||
} catch (Exception e) { | ||
log.error("Invalid request body provided", e); | ||
throw new IllegalArgumentException("Can't initiate move resource request. Incorrect body provided"); | ||
} | ||
|
||
String sourceUrl = request.getSourceUrl(); | ||
if (sourceUrl == null) { | ||
throw new IllegalArgumentException("sourceUrl must be provided"); | ||
} | ||
|
||
String destinationUrl = request.getDestinationUrl(); | ||
if (destinationUrl == null) { | ||
throw new IllegalArgumentException("destinationUrl must be provided"); | ||
} | ||
|
||
String bucketLocation = BlobStorageUtil.buildInitiatorBucket(context); | ||
String bucket = encryptionService.encrypt(bucketLocation); | ||
|
||
ResourceDescription sourceResource = ResourceDescription.fromLink(sourceUrl, encryptionService); | ||
if (!sourceResource.getBucketName().equals(bucket)) { | ||
throw new IllegalArgumentException("sourceUrl do not belong to the user"); | ||
} | ||
|
||
ResourceDescription destinationResource = ResourceDescription.fromLink(destinationUrl, encryptionService); | ||
if (!destinationResource.getBucketName().equals(bucket)) { | ||
throw new IllegalArgumentException("destinationUrl do not belong to the user"); | ||
} | ||
|
||
if (!sourceResource.getType().equals(destinationResource.getType())) { | ||
throw new IllegalArgumentException("source and destination resources must be the same type"); | ||
} | ||
|
||
|
||
return vertx.executeBlocking(() -> lockService.underBucketLock(proxy, bucketLocation, () -> { | ||
resourceOperationService.moveResource(bucket, bucketLocation, sourceResource, destinationResource, request.isOverwrite()); | ||
return null; | ||
})); | ||
}) | ||
.onSuccess(ignore -> context.respond(HttpStatus.OK)) | ||
.onFailure(this::handleServiceError); | ||
|
||
return Future.succeededFuture(); | ||
} | ||
|
||
private void handleServiceError(Throwable error) { | ||
if (error instanceof IllegalArgumentException) { | ||
context.respond(HttpStatus.BAD_REQUEST, error.getMessage()); | ||
} else if (error instanceof HttpException httpException) { | ||
context.respond(httpException.getStatus(), httpException.getMessage()); | ||
} else { | ||
context.respond(HttpStatus.INTERNAL_SERVER_ERROR, error.getMessage()); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/epam/aidial/core/data/MoveResourcesRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.epam.aidial.core.data; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Data | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class MoveResourcesRequest { | ||
String sourceUrl; | ||
String destinationUrl; | ||
boolean overwrite; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/main/java/com/epam/aidial/core/service/ResourceOperationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.epam.aidial.core.service; | ||
|
||
import com.epam.aidial.core.data.ResourceType; | ||
import com.epam.aidial.core.storage.BlobStorage; | ||
import com.epam.aidial.core.storage.ResourceDescription; | ||
import lombok.AllArgsConstructor; | ||
|
||
@AllArgsConstructor | ||
public class ResourceOperationService { | ||
|
||
private final ResourceService resourceService; | ||
private final BlobStorage storage; | ||
private final InvitationService invitationService; | ||
private final ShareService shareService; | ||
|
||
public void moveResource(String bucket, String location, ResourceDescription source, ResourceDescription destination, boolean overwriteIfExists) { | ||
if (source.isFolder() || destination.isFolder()) { | ||
throw new IllegalArgumentException("Moving folders is not supported"); | ||
} | ||
|
||
String sourceResourcePath = source.getAbsoluteFilePath(); | ||
String sourceResourceUrl = source.getUrl(); | ||
String destinationResourcePath = destination.getAbsoluteFilePath(); | ||
String destinationResourceUrl = destination.getUrl(); | ||
|
||
if (!hasResource(source)) { | ||
throw new IllegalArgumentException("Source resource %s do not exists".formatted(sourceResourceUrl)); | ||
} | ||
|
||
ResourceType resourceType = source.getType(); | ||
switch (resourceType) { | ||
case FILE -> { | ||
if (!overwriteIfExists && storage.exists(destinationResourcePath)) { | ||
throw new IllegalArgumentException("Can't move resource %s to %s, because destination resource already exists" | ||
.formatted(sourceResourceUrl, destinationResourceUrl)); | ||
} | ||
storage.copy(sourceResourcePath, destinationResourcePath); | ||
storage.delete(sourceResourcePath); | ||
} | ||
case CONVERSATION, PROMPT -> { | ||
boolean copied = resourceService.copyResource(source, destination, overwriteIfExists); | ||
if (!copied) { | ||
throw new IllegalArgumentException("Can't move resource %s to %s, because destination resource already exists" | ||
.formatted(sourceResourceUrl, destinationResourceUrl)); | ||
} | ||
resourceService.deleteResource(source); | ||
} | ||
default -> throw new IllegalArgumentException("Unsupported resource type " + resourceType); | ||
} | ||
// move source links to destination if any | ||
invitationService.moveResource(bucket, location, source, destination); | ||
// move shared access if any | ||
shareService.moveSharedAccess(bucket, location, source, destination); | ||
} | ||
|
||
private boolean hasResource(ResourceDescription resource) { | ||
return switch (resource.getType()) { | ||
case FILE -> storage.exists(resource.getAbsoluteFilePath()); | ||
case CONVERSATION, PROMPT -> resourceService.hasResource(resource); | ||
default -> throw new IllegalArgumentException("Unsupported resource type " + resource.getType()); | ||
}; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.