Skip to content

Commit

Permalink
fix: custom application URL handling (#396)
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim-Gadalov authored Jul 18, 2024
1 parent 6d3b02c commit e40739d
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ public class CustomApplicationService {
private final JsonObject applicationsConfig;

/**
* Loads a custom application from provided url with permission check
* Loads a custom application from provided decoded url with permission check
*
* @param url - custom application url
* @param decodedUrl - custom application url
* @return - custom application or null if invalid url provided or resource not found
*/
public Application getCustomApplication(String url, ProxyContext context) {
public Application getCustomApplication(String decodedUrl, ProxyContext context) {
ResourceDescription resource;
try {
resource = ResourceDescription.fromAnyUrl(url, encryptionService);
resource = ResourceDescription.fromAnyDecodedUrl(decodedUrl, encryptionService);
} catch (Exception e) {
log.warn("Invalid resource url provided: {}", url);
throw new ResourceNotFoundException("Application %s not found".formatted(url));
log.warn("Invalid resource url provided: {}", decodedUrl);
throw new ResourceNotFoundException("Application %s not found".formatted(decodedUrl));
}

if (resource.getType() != ResourceType.APPLICATION) {
Expand All @@ -54,7 +54,7 @@ public Application getCustomApplication(String url, ProxyContext context) {

boolean hasAccess = accessService.hasReadAccess(resource, context);
if (!hasAccess) {
throw new PermissionDeniedException("User don't have access to the deployment " + url);
throw new PermissionDeniedException("User don't have access to the deployment " + resource.getUrl());
}

String applicationBody = resourceService.getResource(resource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,39 @@ public static ResourceDescription fromAnyUrl(String url, EncryptionService encry
return fromUrl(url, null, null, encryption);
}

public static ResourceDescription fromAnyDecodedUrl(String url, EncryptionService encryption) {
String[] parts = url.split(BlobStorageUtil.PATH_SEPARATOR);

if (parts.length < 2) {
throw new IllegalArgumentException("Url has less than two segments: " + url);
}

if (url.startsWith(BlobStorageUtil.PATH_SEPARATOR)) {
throw new IllegalArgumentException("Url must not start with " + BlobStorageUtil.PATH_SEPARATOR + ", but: " + url);
}

if (parts.length == 2 && !url.endsWith(BlobStorageUtil.PATH_SEPARATOR)) {
throw new IllegalArgumentException("Url must start with resource/bucket/, but: " + url);
}

ResourceType resourceType = ResourceType.of(parts[0]);
String bucket = parts[1];
String location = null;

if (bucket.equals(BlobStorageUtil.PUBLIC_BUCKET)) {
location = BlobStorageUtil.PUBLIC_LOCATION;
} else if (encryption != null) {
location = encryption.decrypt(bucket);
}

if (location == null) {
throw new IllegalArgumentException("Url has invalid bucket: " + url);
}

String relativePath = url.substring(parts[0].length() + parts[1].length() + 2);
return fromDecoded(resourceType, bucket, location, relativePath);
}

@Override
public String toString() {
return getUrl();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.epam.aidial.core.storage;

import com.epam.aidial.core.config.Encryption;
import com.epam.aidial.core.data.ResourceType;
import com.epam.aidial.core.security.EncryptionService;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand Down Expand Up @@ -193,4 +195,26 @@ public void testInvalidPublicLinks() {
assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicUrl("publications/public"));
assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicUrl("publications/private/"));
}

@Test
public void testFromAnyDecodedUrl() {
EncryptionService encryptionService = new EncryptionService(new Encryption("password", "salt"));
String location = "Users/User1/";
String bucket = encryptionService.encrypt(location);

ResourceDescription privateResource = ResourceDescription.fromAnyDecodedUrl("files/%s/my folder/some file".formatted(bucket), encryptionService);
assertEquals(ResourceType.FILE, privateResource.getType());
assertEquals(bucket, privateResource.getBucketName());
assertEquals(location, privateResource.getBucketLocation());
assertEquals("files/" + bucket + "/my%20folder/some%20file", privateResource.getUrl());
assertFalse(privateResource.isFolder());
assertTrue(privateResource.isPrivate());

ResourceDescription publicResource = ResourceDescription.fromAnyDecodedUrl("applications/public/my folder/some app", encryptionService);
assertEquals(ResourceType.APPLICATION, publicResource.getType());
assertEquals("public", publicResource.getBucketName());
assertEquals("applications/public/my%20folder/some%20app", publicResource.getUrl());
assertFalse(publicResource.isFolder());
assertTrue(publicResource.isPublic());
}
}

0 comments on commit e40739d

Please sign in to comment.