diff --git a/src/main/java/com/epam/aidial/core/AiDial.java b/src/main/java/com/epam/aidial/core/AiDial.java index d2f711630..1aca0aaa9 100644 --- a/src/main/java/com/epam/aidial/core/AiDial.java +++ b/src/main/java/com/epam/aidial/core/AiDial.java @@ -73,9 +73,6 @@ public class AiDial { private BlobStorage storage; private ResourceService resourceService; - private InvitationService invitationService; - private ShareService shareService; - private PublicationService publicationService; private LongSupplier clock = System::currentTimeMillis; private Supplier generator = () -> UUID.randomUUID().toString().replace("-", ""); diff --git a/src/main/java/com/epam/aidial/core/service/PublicationService.java b/src/main/java/com/epam/aidial/core/service/PublicationService.java index 5a4c58eb1..2a6d7e7ef 100644 --- a/src/main/java/com/epam/aidial/core/service/PublicationService.java +++ b/src/main/java/com/epam/aidial/core/service/PublicationService.java @@ -5,6 +5,7 @@ import com.epam.aidial.core.data.ResourceUrl; import com.epam.aidial.core.security.EncryptionService; import com.epam.aidial.core.storage.BlobStorage; +import com.epam.aidial.core.storage.BlobStorageUtil; import com.epam.aidial.core.storage.ResourceDescription; import com.epam.aidial.core.util.ProxyUtil; import com.epam.aidial.core.util.UrlUtil; @@ -23,7 +24,8 @@ import javax.annotation.Nullable; import static com.epam.aidial.core.storage.BlobStorageUtil.PATH_SEPARATOR; -import static com.epam.aidial.core.storage.ResourceDescription.PUBLIC_BUCKET; +import static com.epam.aidial.core.storage.BlobStorageUtil.PUBLIC_BUCKET; +import static com.epam.aidial.core.storage.BlobStorageUtil.PUBLIC_LOCATION; @RequiredArgsConstructor public class PublicationService { @@ -33,7 +35,7 @@ public class PublicationService { }; private static final ResourceDescription PUBLIC_PUBLICATIONS = ResourceDescription.fromDecoded( - ResourceType.PUBLICATION, PUBLIC_BUCKET, ResourceDescription.PUBLIC_LOCATION, + ResourceType.PUBLICATION, PUBLIC_BUCKET, PUBLIC_LOCATION, PUBLICATIONS_NAME); private final EncryptionService encryption; diff --git a/src/main/java/com/epam/aidial/core/storage/BlobStorageUtil.java b/src/main/java/com/epam/aidial/core/storage/BlobStorageUtil.java index 724d9c9d0..5b2d1b37d 100644 --- a/src/main/java/com/epam/aidial/core/storage/BlobStorageUtil.java +++ b/src/main/java/com/epam/aidial/core/storage/BlobStorageUtil.java @@ -9,14 +9,15 @@ @UtilityClass public class BlobStorageUtil { - public static final String APPDATA_PATTERN = "appdata/%s"; + public static final String PATH_SEPARATOR = "/"; - private static final String USER_BUCKET_PATTERN = "Users/%s/"; + public static final String PUBLIC_BUCKET = "public"; + public static final String PUBLIC_LOCATION = PUBLIC_BUCKET + PATH_SEPARATOR; + public static final String APPDATA_PATTERN = "appdata/%s"; + private static final String USER_BUCKET_PATTERN = "Users/%s/"; private static final String API_KEY_BUCKET_PATTERN = "Keys/%s/"; - public static final String PATH_SEPARATOR = "/"; - public String getContentType(String fileName) { String mimeType = MimeMapping.getMimeTypeForFilename(fileName); return mimeType == null ? "application/octet-stream" : mimeType; diff --git a/src/main/java/com/epam/aidial/core/storage/ResourceDescription.java b/src/main/java/com/epam/aidial/core/storage/ResourceDescription.java index 2d059eea1..973ae4350 100644 --- a/src/main/java/com/epam/aidial/core/storage/ResourceDescription.java +++ b/src/main/java/com/epam/aidial/core/storage/ResourceDescription.java @@ -19,9 +19,6 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) public class ResourceDescription { - public static final String PUBLIC_BUCKET = "public"; - public static final String PUBLIC_LOCATION = PUBLIC_BUCKET + BlobStorageUtil.PATH_SEPARATOR; - private static final Set INVALID_FILE_NAME_CHARS = Set.of('/', '{', '}'); private static final int MAX_PATH_SIZE = 900; @@ -169,10 +166,19 @@ public static ResourceDescription fromLink(String link, EncryptionService encryp private static ResourceDescription fromLink(String link, String bucketEncoded, String bucketDecoded) { String[] parts = link.split(BlobStorageUtil.PATH_SEPARATOR); + if (parts.length < 2) { throw new IllegalArgumentException("Invalid resource link provided " + link); } + if (link.startsWith(BlobStorageUtil.PATH_SEPARATOR)) { + throw new IllegalArgumentException("Link must not start with " + BlobStorageUtil.PATH_SEPARATOR + ", but: " + link); + } + + if (parts.length == 2 && !link.endsWith(BlobStorageUtil.PATH_SEPARATOR)) { + throw new IllegalArgumentException("Link must start resource/bucket/, but: " + BlobStorageUtil.PATH_SEPARATOR + ": " + link); + } + ResourceType resourceType = ResourceType.of(UrlUtil.decodePath(parts[0])); String bucket = UrlUtil.decodePath(parts[1]); if (!bucket.equals(bucketEncoded)) { @@ -188,7 +194,7 @@ public static ResourceDescription fromBucketLink(String link, ResourceDescriptio } public static ResourceDescription fromPublicLink(String link) { - return fromLink(link, PUBLIC_BUCKET, PUBLIC_LOCATION); + return fromLink(link, BlobStorageUtil.PUBLIC_BUCKET, BlobStorageUtil.PUBLIC_LOCATION); } private static ResourceDescription from(ResourceType type, String bucketName, String bucketLocation, diff --git a/src/test/java/com/epam/aidial/core/ResourceBaseTest.java b/src/test/java/com/epam/aidial/core/ResourceBaseTest.java index c5848fe39..0846a8e1a 100644 --- a/src/test/java/com/epam/aidial/core/ResourceBaseTest.java +++ b/src/test/java/com/epam/aidial/core/ResourceBaseTest.java @@ -236,13 +236,6 @@ Response send(HttpMethod method, String path, String queryParams, String body, S } } - @SneakyThrows - private static String pretty(String json) { - ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); - Object jsonObject = mapper.readValue(json, Object.class); - return mapper.writeValueAsString(jsonObject); - } - record Response(int status, String body) { public boolean ok() { return status() == 200; diff --git a/src/test/java/com/epam/aidial/core/storage/ResourceDescriptionTest.java b/src/test/java/com/epam/aidial/core/storage/ResourceDescriptionTest.java index e29fb825c..4cac68ddb 100644 --- a/src/test/java/com/epam/aidial/core/storage/ResourceDescriptionTest.java +++ b/src/test/java/com/epam/aidial/core/storage/ResourceDescriptionTest.java @@ -152,4 +152,35 @@ public void testResourceWithInvalidFilename() { assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromEncoded(ResourceType.FILE, "bucket", "location/", "folder1/file%7D.txt")); } + + @Test + public void testValidPublicLinks() { + assertEquals( + ResourceDescription.fromPublicLink("publications/public/"), + ResourceDescription.fromEncoded(ResourceType.PUBLICATION, "public", "public/", "") + ); + + assertEquals( + ResourceDescription.fromPublicLink("publications/public/file"), + ResourceDescription.fromEncoded(ResourceType.PUBLICATION, "public", "public/", "file") + ); + + assertEquals( + ResourceDescription.fromPublicLink("publications/public/folder/"), + ResourceDescription.fromEncoded(ResourceType.PUBLICATION, "public", "public/", "folder/") + ); + + assertEquals( + ResourceDescription.fromPublicLink("publications/public/%30").getName(), + "0" + ); + } + + @Test + public void testInvalidPublicLinks() { + assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicLink("/publications/public/")); + assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicLink("publications/public")); + assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicLink("publications/public")); + assertThrows(IllegalArgumentException.class, () -> ResourceDescription.fromPublicLink("publications/private/")); + } }