From 40dac6b0a7a7d6e8cdd538cb78e32ff0bc422926 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 15:28:43 +0100 Subject: [PATCH 1/8] Fn to add server specific files to the proxying request for applications with schema --- .../controller/DeploymentPostController.java | 4 +- .../CollectRequestApplicationFilesFn.java | 62 +++++++++++++++++++ .../util/ApplicationTypeSchemaUtils.java | 15 ++++- .../server/validation/DialFileKeyword.java | 15 ++++- .../core/server/validation/ListCollector.java | 14 +++++ .../util/ApplicationTypeSchemaUtilsTest.java | 44 +++++++++++++ 6 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java diff --git a/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java b/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java index 926a673d..9ed36b26 100644 --- a/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java +++ b/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java @@ -12,6 +12,7 @@ import com.epam.aidial.core.server.data.ApiKeyData; import com.epam.aidial.core.server.data.ErrorData; import com.epam.aidial.core.server.function.BaseRequestFunction; +import com.epam.aidial.core.server.function.CollectRequestApplicationFilesFn; import com.epam.aidial.core.server.function.CollectRequestAttachmentsFn; import com.epam.aidial.core.server.function.CollectRequestDataFn; import com.epam.aidial.core.server.function.CollectResponseAttachmentsFn; @@ -73,7 +74,8 @@ public DeploymentPostController(Proxy proxy, ProxyContext context) { new ApplyDefaultDeploymentSettingsFn(proxy, context), new EnhanceAssistantRequestFn(proxy, context), new EnhanceModelRequestFn(proxy, context), - new AppendApplicationPropertiesFn(proxy, context)); + new AppendApplicationPropertiesFn(proxy, context), + new CollectRequestApplicationFilesFn(proxy, context)); } public Future handle(String deploymentId, String deploymentApi) { diff --git a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java new file mode 100644 index 00000000..5d949e3d --- /dev/null +++ b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java @@ -0,0 +1,62 @@ +package com.epam.aidial.core.server.function; + +import com.epam.aidial.core.config.Application; +import com.epam.aidial.core.config.Deployment; +import com.epam.aidial.core.server.Proxy; +import com.epam.aidial.core.server.ProxyContext; +import com.epam.aidial.core.server.data.ApiKeyData; +import com.epam.aidial.core.server.data.AutoSharedData; +import com.epam.aidial.core.server.security.AccessService; +import com.epam.aidial.core.server.util.ApplicationTypeSchemaUtils; +import com.epam.aidial.core.server.util.ProxyUtil; +import com.epam.aidial.core.storage.data.ResourceAccessType; +import com.epam.aidial.core.storage.http.HttpException; +import com.epam.aidial.core.storage.http.HttpStatus; +import com.epam.aidial.core.storage.resource.ResourceDescriptor; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + + +@Slf4j +public class CollectRequestApplicationFilesFn extends BaseRequestFunction { + public CollectRequestApplicationFilesFn(Proxy proxy, ProxyContext context) { + super(proxy, context); + } + + @Override + public Boolean apply(ObjectNode tree) { + Deployment deployment = context.getDeployment(); + if (!(deployment instanceof Application application && application.getApplicationTypeSchemaId() != null)) { + return false; + } + List resources = ApplicationTypeSchemaUtils.getServerFiles(context.getConfig(), application, proxy.getEncryptionService(), + proxy.getResourceService()); + ApiKeyData keyData = context.getProxyApiKeyData(); + appendFilesToProxyApiKeyData(keyData, resources); + String perRequestKey = context.getProxyApiKeyData().getPerRequestKey(); + if (perRequestKey == null) { //This class may be not the one who modifies the perRequestKey + proxy.getApiKeyStore().assignPerRequestApiKey(keyData); + } else { + proxy.getApiKeyStore().updatePerRequestApiKey(perRequestKey, json -> ProxyUtil.convertToString(keyData)); + } + return false; + } + + private void appendFilesToProxyApiKeyData(ApiKeyData apiKeyData, List resources) { + for (ResourceDescriptor resource : resources) { + String resourceUrl = resource.getUrl(); + AccessService accessService = proxy.getAccessService(); + if (accessService.hasReadAccess(resource, context)) { + if (resource.isFolder()) { + apiKeyData.getAttachedFolders().put(resourceUrl, new AutoSharedData(ResourceAccessType.READ_ONLY)); + } else { + apiKeyData.getAttachedFiles().put(resourceUrl, new AutoSharedData(ResourceAccessType.READ_ONLY)); + } + } else { + throw new HttpException(HttpStatus.FORBIDDEN, "Access denied to the file %s".formatted(resourceUrl)); + } + } + } +} diff --git a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java index b488ff29..2b669f81 100644 --- a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java +++ b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java @@ -154,8 +154,19 @@ public static void replaceCustomAppFiles(Application application, Map getServerFiles(Config config, Application application, EncryptionService encryptionService, + ResourceService resourceService) { + return getFiles(config, application, encryptionService, resourceService, ListCollector.FileCollectorType.ONLY_SERVER_FILES); + } + + public static List getFiles(Config config, Application application, EncryptionService encryptionService, + ResourceService resourceService) { + return getFiles(config, application, encryptionService, resourceService, ListCollector.FileCollectorType.ALL_FILES); + } + @SuppressWarnings("unchecked") - public static List getFiles(Config config, Application application, EncryptionService encryptionService, ResourceService resourceService) { + private static List getFiles(Config config, Application application, EncryptionService encryptionService, + ResourceService resourceService, ListCollector.FileCollectorType collectorName) { try { String customApplicationSchema = getCustomApplicationSchemaOrThrow(config, application); if (customApplicationSchema == null) { @@ -169,7 +180,7 @@ public static List getFiles(Config config, Application appli if (!validationResult.isEmpty()) { throw new ApplicationTypeSchemaValidationException("Failed to validate custom app against the schema", validationResult); } - ListCollector propsCollector = (ListCollector) collectorContext.getCollectorMap().get("file"); + ListCollector propsCollector = (ListCollector) collectorContext.getCollectorMap().get(collectorName.getValue()); if (propsCollector == null) { return Collections.emptyList(); } diff --git a/server/src/main/java/com/epam/aidial/core/server/validation/DialFileKeyword.java b/server/src/main/java/com/epam/aidial/core/server/validation/DialFileKeyword.java index cdd930e7..04cabbdc 100644 --- a/server/src/main/java/com/epam/aidial/core/server/validation/DialFileKeyword.java +++ b/server/src/main/java/com/epam/aidial/core/server/validation/DialFileKeyword.java @@ -33,12 +33,16 @@ private static class DialFileCollectorValidator extends BaseJsonValidator { private static final ErrorMessageType ERROR_MESSAGE_TYPE = () -> "dial:file"; private final Boolean value; + private final Boolean isServerProp; public DialFileCollectorValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, Keyword keyword, ValidationContext validationContext, boolean suppressSubSchemaRetrieval) { super(schemaLocation, evaluationPath, schemaNode, parentSchema, ERROR_MESSAGE_TYPE, keyword, validationContext, suppressSubSchemaRetrieval); this.value = schemaNode.booleanValue(); + JsonNode metaNode = parentSchema.getSchemaNode().get("dial:meta"); + JsonNode propertyKindNode = (metaNode != null) ? metaNode.get("dial:propertyKind") : null; + this.isServerProp = (propertyKindNode != null) && propertyKindNode.asText().equalsIgnoreCase("server"); } @Override @@ -46,9 +50,14 @@ public DialFileCollectorValidator(SchemaLocation schemaLocation, JsonNodePath ev public Set validate(ExecutionContext executionContext, JsonNode jsonNode, JsonNode jsonNode1, JsonNodePath jsonNodePath) { if (value) { CollectorContext collectorContext = executionContext.getCollectorContext(); - ListCollector serverPropsCollector = (ListCollector) collectorContext.getCollectorMap() - .computeIfAbsent("file", k -> new ListCollector()); - serverPropsCollector.combine(List.of(jsonNode.asText())); + ListCollector fileCollector = (ListCollector) collectorContext.getCollectorMap() + .computeIfAbsent(ListCollector.FileCollectorType.ALL_FILES.getValue(), k -> new ListCollector()); + fileCollector.combine(List.of(jsonNode.asText())); + if (isServerProp) { + ListCollector serverFileCollector = (ListCollector) collectorContext.getCollectorMap() + .computeIfAbsent(ListCollector.FileCollectorType.ONLY_SERVER_FILES.getValue(), k -> new ListCollector()); + serverFileCollector.combine(List.of(jsonNode.asText())); + } } return Set.of(); } diff --git a/server/src/main/java/com/epam/aidial/core/server/validation/ListCollector.java b/server/src/main/java/com/epam/aidial/core/server/validation/ListCollector.java index 396c24f9..6e15930d 100644 --- a/server/src/main/java/com/epam/aidial/core/server/validation/ListCollector.java +++ b/server/src/main/java/com/epam/aidial/core/server/validation/ListCollector.java @@ -1,11 +1,25 @@ package com.epam.aidial.core.server.validation; import com.networknt.schema.Collector; +import lombok.Getter; import java.util.ArrayList; import java.util.List; public class ListCollector implements Collector> { + + @Getter + public enum FileCollectorType { + ALL_FILES("file"), + ONLY_SERVER_FILES("server_file"); + + private final String value; + + FileCollectorType(String value) { + this.value = value; + } + } + private final List references = new ArrayList<>(); @Override diff --git a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java index f6a9a5ac..3de5b5f8 100644 --- a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java @@ -360,4 +360,48 @@ public void getFiles_throwsException_whenResourceNotFound() { Assertions.assertThrows(ApplicationTypeSchemaValidationException.class, () -> ApplicationTypeSchemaUtils.getFiles(config, application, encryptionService, resourceService)); } + + @Test + public void getServerFiles_returnsListOfServerFiles_whenSchemaExists() { + application.setApplicationTypeSchemaId(URI.create("schemaId")); + application.setApplicationProperties(customProperties); + when(config.getCustomApplicationSchema(any())).thenReturn(schema); + + EncryptionService encryptionService = mock(EncryptionService.class); + ResourceService resourceService = mock(ResourceService.class); + + when(resourceService.hasResource(any())).thenReturn(true); + + List result = ApplicationTypeSchemaUtils.getServerFiles(config, application, encryptionService, resourceService); + + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(result.get(0).getUrl(), serverProperties.get("serverFile")); + } + + @Test + public void getServerFiles_returnsEmptyList_whenSchemaIsNull() { + application.setApplicationTypeSchemaId(null); + + EncryptionService encryptionService = mock(EncryptionService.class); + ResourceService resourceService = mock(ResourceService.class); + + List result = ApplicationTypeSchemaUtils.getServerFiles(config, application, encryptionService, resourceService); + + Assertions.assertTrue(result.isEmpty()); + } + + @Test + public void getServerFiles_throwsException_whenResourceNotFound() { + application.setApplicationTypeSchemaId(URI.create("schemaId")); + application.setApplicationProperties(customProperties); + when(config.getCustomApplicationSchema(any())).thenReturn(schema); + + EncryptionService encryptionService = mock(EncryptionService.class); + ResourceService resourceService = mock(ResourceService.class); + + when(resourceService.hasResource(any())).thenReturn(false); + + Assertions.assertThrows(ApplicationTypeSchemaValidationException.class, () -> + ApplicationTypeSchemaUtils.getServerFiles(config, application, encryptionService, resourceService)); + } } From 4f48f0de964d82d38a1e99a4f4ab7aa93632562b Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 19:13:08 +0100 Subject: [PATCH 2/8] CollectRequestApplicationFilesFnTest + ApplicationTypeResourceException --- .../server/controller/ResourceController.java | 4 + .../CollectRequestApplicationFilesFn.java | 35 ++-- .../util/ApplicationTypeSchemaUtils.java | 10 +- .../ApplicationTypeResourceException.java | 20 ++ ...licationTypeSchemaValidationException.java | 4 - .../CollectRequestApplicationFilesFnTest.java | 192 ++++++++++++++++++ ...pendCustomApplicationPropertiesFnTest.java | 59 +++--- 7 files changed, 276 insertions(+), 48 deletions(-) create mode 100644 server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java create mode 100644 server/src/test/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFnTest.java diff --git a/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java b/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java index c6894025..c881d941 100644 --- a/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java +++ b/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java @@ -17,6 +17,7 @@ import com.epam.aidial.core.server.util.ApplicationTypeSchemaUtils; import com.epam.aidial.core.server.util.ProxyUtil; import com.epam.aidial.core.server.util.ResourceDescriptorFactory; +import com.epam.aidial.core.server.validation.ApplicationTypeResourceException; import com.epam.aidial.core.server.validation.ApplicationTypeSchemaValidationException; import com.epam.aidial.core.storage.data.MetadataBase; import com.epam.aidial.core.storage.data.ResourceItemMetadata; @@ -37,6 +38,7 @@ import java.util.List; import static com.epam.aidial.core.storage.http.HttpStatus.BAD_REQUEST; +import static com.epam.aidial.core.storage.http.HttpStatus.FORBIDDEN; import static com.epam.aidial.core.storage.http.HttpStatus.INTERNAL_SERVER_ERROR; @Slf4j @@ -178,6 +180,8 @@ private void validateCustomApplication(Application application) { }); } catch (ValidationException | IllegalArgumentException | ApplicationTypeSchemaValidationException e) { throw new HttpException(BAD_REQUEST, " Custom application validation failed", e); + } catch (ApplicationTypeResourceException e) { + throw new HttpException(FORBIDDEN, "Failed to access application resource " + e.getResourceUri(), e); } catch (ApplicationTypeSchemaProcessingException e) { throw new HttpException(INTERNAL_SERVER_ERROR, "Custom application processing exception", e); } diff --git a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java index 5d949e3d..24af4461 100644 --- a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java +++ b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java @@ -9,6 +9,7 @@ import com.epam.aidial.core.server.security.AccessService; import com.epam.aidial.core.server.util.ApplicationTypeSchemaUtils; import com.epam.aidial.core.server.util.ProxyUtil; +import com.epam.aidial.core.server.validation.ApplicationTypeResourceException; import com.epam.aidial.core.storage.data.ResourceAccessType; import com.epam.aidial.core.storage.http.HttpException; import com.epam.aidial.core.storage.http.HttpStatus; @@ -27,21 +28,29 @@ public CollectRequestApplicationFilesFn(Proxy proxy, ProxyContext context) { @Override public Boolean apply(ObjectNode tree) { - Deployment deployment = context.getDeployment(); - if (!(deployment instanceof Application application && application.getApplicationTypeSchemaId() != null)) { + try { + Deployment deployment = context.getDeployment(); + if (!(deployment instanceof Application application && application.getApplicationTypeSchemaId() != null)) { + return false; + } + List resources = ApplicationTypeSchemaUtils.getServerFiles(context.getConfig(), application, proxy.getEncryptionService(), + proxy.getResourceService()); + ApiKeyData keyData = context.getProxyApiKeyData(); + appendFilesToProxyApiKeyData(keyData, resources); + String perRequestKey = keyData.getPerRequestKey(); + if (perRequestKey == null) { //This class may be not the one who modifies the perRequestKey + proxy.getApiKeyStore().assignPerRequestApiKey(keyData); + } else { + proxy.getApiKeyStore().updatePerRequestApiKey(perRequestKey, json -> ProxyUtil.convertToString(keyData)); + } return false; + } catch (HttpException ex) { + throw ex; + } catch (ApplicationTypeResourceException ex) { + throw new HttpException(HttpStatus.FORBIDDEN, ex.getMessage()); + } catch (Exception e) { + throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, e.getMessage()); } - List resources = ApplicationTypeSchemaUtils.getServerFiles(context.getConfig(), application, proxy.getEncryptionService(), - proxy.getResourceService()); - ApiKeyData keyData = context.getProxyApiKeyData(); - appendFilesToProxyApiKeyData(keyData, resources); - String perRequestKey = context.getProxyApiKeyData().getPerRequestKey(); - if (perRequestKey == null) { //This class may be not the one who modifies the perRequestKey - proxy.getApiKeyStore().assignPerRequestApiKey(keyData); - } else { - proxy.getApiKeyStore().updatePerRequestApiKey(perRequestKey, json -> ProxyUtil.convertToString(keyData)); - } - return false; } private void appendFilesToProxyApiKeyData(ApiKeyData apiKeyData, List resources) { diff --git a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java index 2b669f81..30742448 100644 --- a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java +++ b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java @@ -4,6 +4,7 @@ import com.epam.aidial.core.config.Config; import com.epam.aidial.core.server.ProxyContext; import com.epam.aidial.core.server.security.EncryptionService; +import com.epam.aidial.core.server.validation.ApplicationTypeResourceException; import com.epam.aidial.core.server.validation.ApplicationTypeSchemaValidationException; import com.epam.aidial.core.server.validation.DialFileKeyword; import com.epam.aidial.core.server.validation.DialMetaKeyword; @@ -172,6 +173,9 @@ private static List getFiles(Config config, Application appl if (customApplicationSchema == null) { return Collections.emptyList(); } + if (application.getApplicationProperties() == null) { + throw new ApplicationTypeSchemaValidationException("Typed application's properties not set"); + } JsonSchema appSchema = SCHEMA_FACTORY.getSchema(customApplicationSchema); CollectorContext collectorContext = new CollectorContext(); String customPropsJson = ProxyUtil.MAPPER.writeValueAsString(application.getApplicationProperties()); @@ -189,15 +193,15 @@ private static List getFiles(Config config, Application appl try { ResourceDescriptor descriptor = ResourceDescriptorFactory.fromAnyUrl(item, encryptionService); if (!descriptor.isFolder() && !resourceService.hasResource(descriptor)) { - throw new ApplicationTypeSchemaValidationException("Resource listed as dependent to the application not found or inaccessible: " + item); + throw new ApplicationTypeResourceException("Resource listed as dependent to the application not found or inaccessible", item); } result.add(descriptor); } catch (IllegalArgumentException e) { - throw new ApplicationTypeSchemaValidationException("Failed to get resource descriptor for url: " + item, e); + throw new ApplicationTypeResourceException("Failed to get resource descriptor for url", item, e); } } return result; - } catch (ApplicationTypeSchemaValidationException e) { + } catch (ApplicationTypeSchemaValidationException | ApplicationTypeResourceException e) { throw e; } catch (Exception e) { throw new ApplicationTypeSchemaProcessingException("Failed to obtain list of files attached to the custom app", e); diff --git a/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java new file mode 100644 index 00000000..fbc660d9 --- /dev/null +++ b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java @@ -0,0 +1,20 @@ +package com.epam.aidial.core.server.validation; + +import lombok.Getter; + +@Getter +public class ApplicationTypeResourceException extends RuntimeException { + + private final String resourceUri; + + public ApplicationTypeResourceException(String message, String resourceUri, Throwable cause) { + super(message, cause); + this.resourceUri = resourceUri; + } + + public ApplicationTypeResourceException(String message, String resourceUri) { + super(message); + this.resourceUri = resourceUri; + } + +} \ No newline at end of file diff --git a/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeSchemaValidationException.java b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeSchemaValidationException.java index 5b895648..f1f4dab6 100644 --- a/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeSchemaValidationException.java +++ b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeSchemaValidationException.java @@ -14,10 +14,6 @@ public ApplicationTypeSchemaValidationException(String message, Set customProps = new HashMap<>(); + customProps.put("clientFile", "files/public/valid-file-path/valid-sub-path/valid%20file%20name1.ext"); + customProps.put("serverFile", serverFile); + application.setApplicationProperties(customProps); + when(config.getCustomApplicationSchema(eq(URI.create("customSchemaId")))).thenReturn(schema); + when(accessService.hasReadAccess(any(), any())).thenReturn(true); + when(resourceService.hasResource(any())).thenReturn(true); + ApiKeyData apiKeyData = new ApiKeyData(); + when(context.getProxyApiKeyData()).thenReturn(apiKeyData); + + boolean result = fn.apply(tree); + + assertFalse(result); + assertNotNull(apiKeyData.getAttachedFiles().get(serverFile)); + assertNotNull(apiKeyData.getPerRequestKey()); + assertEquals(1, apiKeyData.getAttachedFiles().size()); + } + + @Test + void apply_throws_whenResourceServiceHasNoResource() { + when(proxy.getResourceService()).thenReturn(resourceService); + when(context.getConfig()).thenReturn(config); + String serverFile = "files/public/valid-file-path/valid-sub-path/valid%20file%20name2.ext"; + when(context.getDeployment()).thenReturn(application); + application.setApplicationTypeSchemaId(URI.create("customSchemaId")); + Map customProps = new HashMap<>(); + customProps.put("clientFile", "files/public/valid-file-path/valid-sub-path/valid%20file%20name1.ext"); + customProps.put("serverFile", serverFile); + application.setApplicationProperties(customProps); + when(config.getCustomApplicationSchema(eq(URI.create("customSchemaId")))).thenReturn(schema); + when(resourceService.hasResource(any())).thenReturn(false); //Has No Resource + + Assertions.assertThrows(HttpException.class, () -> fn.apply(tree)); + } + + @Test + void apply_throws_whenAccessServiceHasNoReadAccess() { + when(proxy.getAccessService()).thenReturn(accessService); + when(proxy.getResourceService()).thenReturn(resourceService); + when(context.getProxyApiKeyData()).thenReturn(new ApiKeyData()); + when(context.getConfig()).thenReturn(config); + String serverFile = "files/public/valid-file-path/valid-sub-path/valid%20file%20name2.ext"; + when(context.getDeployment()).thenReturn(application); + application.setApplicationTypeSchemaId(URI.create("customSchemaId")); + Map customProps = new HashMap<>(); + customProps.put("clientFile", "files/public/valid-file-path/valid-sub-path/valid%20file%20name1.ext"); + customProps.put("serverFile", serverFile); + application.setApplicationProperties(customProps); + when(config.getCustomApplicationSchema(eq(URI.create("customSchemaId")))).thenReturn(schema); + when(accessService.hasReadAccess(any(), any())).thenReturn(false); //Has no Read Access + when(resourceService.hasResource(any())).thenReturn(true); + ApiKeyData apiKeyData = new ApiKeyData(); + when(context.getProxyApiKeyData()).thenReturn(apiKeyData); + + Assertions.assertThrows(HttpException.class, () -> fn.apply(tree)); + } +} \ No newline at end of file diff --git a/server/src/test/java/com/epam/aidial/core/server/function/enhancement/AppendCustomApplicationPropertiesFnTest.java b/server/src/test/java/com/epam/aidial/core/server/function/enhancement/AppendCustomApplicationPropertiesFnTest.java index 9cf05f0e..c5237b1f 100644 --- a/server/src/test/java/com/epam/aidial/core/server/function/enhancement/AppendCustomApplicationPropertiesFnTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/function/enhancement/AppendCustomApplicationPropertiesFnTest.java @@ -43,34 +43,37 @@ public class AppendCustomApplicationPropertiesFnTest { private AppendApplicationPropertiesFn function; - private final String schema = "{" - + "\"$schema\": \"https://dial.epam.com/application_type_schemas/schema#\"," - + "\"$id\": \"https://mydial.epam.com/custom_application_schemas/specific_application_type\"," - + "\"dial:applicationTypeEditorUrl\": \"https://mydial.epam.com/specific_application_type_editor\"," - + "\"dial:applicationTypeDisplayName\": \"Specific Application Type\"," - + "\"dial:applicationTypeCompletionEndpoint\": \"http://specific_application_service/opeani/v1/completion\"," - + "\"properties\": {" - + " \"clientFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"client\"," - + " \"dial:propertyOrder\": 1" - + " }," - + " \"dial:file\" : true" - + " }," - + " \"serverFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"server\"," - + " \"dial:propertyOrder\": 2" - + " }," - + " \"dial:file\" : true" - + " }" - + "}," - + "\"required\": [\"clientFile\"]" - + "}"; + private final String schema = """ + { + "$schema": "https://dial.epam.com/application_type_schemas/schema#", + "$id": "https://mydial.epam.com/custom_application_schemas/specific_application_type", + "dial:applicationTypeEditorUrl": "https://mydial.epam.com/specific_application_type_editor", + "dial:applicationTypeDisplayName": "Specific Application Type", + "dial:applicationTypeCompletionEndpoint": "http://specific_application_service/opeani/v1/completion", + "properties": { + "clientFile": { + "type": "string", + "format": "dial-file-encoded", + "dial:meta": { + "dial:propertyKind": "client", + "dial:propertyOrder": 1 + }, + "dial:file": true + }, + "serverFile": { + "type": "string", + "format": "dial-file-encoded", + "dial:meta": { + "dial:propertyKind": "server", + "dial:propertyOrder": 2 + }, + "dial:file": true + } + }, + "required": [ + "clientFile" + ] + }"""; @BeforeEach void setUp() { From 7fcfbeb85c042306d5c22329aa9e1845e034fbf1 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 19:18:52 +0100 Subject: [PATCH 3/8] change to forbidden status code in ResourceApiTest --- .../test/java/com/epam/aidial/core/server/ResourceApiTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/com/epam/aidial/core/server/ResourceApiTest.java b/server/src/test/java/com/epam/aidial/core/server/ResourceApiTest.java index ce49fed1..4921d405 100644 --- a/server/src/test/java/com/epam/aidial/core/server/ResourceApiTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/ResourceApiTest.java @@ -403,7 +403,7 @@ void testApplicationWithTypeSchemaCreation_Failed_FailAccessFile() { "description": "My application description" } """); - Assertions.assertEquals(400, response.status()); + Assertions.assertEquals(403, response.status()); } @Test From 26de26763afedd86586bc7d37b13561b38dfdbeb Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 19:37:09 +0100 Subject: [PATCH 4/8] moved property existence check to feet custom application api tests --- .../server/controller/ResourceController.java | 19 +++++++------------ .../CollectRequestApplicationFilesFn.java | 3 +++ .../util/ApplicationTypeSchemaUtils.java | 3 --- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java b/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java index c881d941..8875bfb1 100644 --- a/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java +++ b/server/src/main/java/com/epam/aidial/core/server/controller/ResourceController.java @@ -12,7 +12,6 @@ import com.epam.aidial.core.server.service.ApplicationService; import com.epam.aidial.core.server.service.PermissionDeniedException; import com.epam.aidial.core.server.service.ResourceNotFoundException; -import com.epam.aidial.core.server.service.ShareService; import com.epam.aidial.core.server.util.ApplicationTypeSchemaProcessingException; import com.epam.aidial.core.server.util.ApplicationTypeSchemaUtils; import com.epam.aidial.core.server.util.ProxyUtil; @@ -132,11 +131,9 @@ private Future getResource(ResourceDescriptor descriptor, boolean hasWriteAcc Future> responseFuture = (descriptor.getType() == ResourceTypes.APPLICATION) ? getApplicationData(descriptor, hasWriteAccess, etagHeader) : getResourceData(descriptor, etagHeader); - responseFuture.onSuccess(pair -> { - context.putHeader(HttpHeaders.ETAG, pair.getKey().getEtag()) - .exposeHeaders() - .respond(HttpStatus.OK, pair.getValue()); - }) + responseFuture.onSuccess(pair -> context.putHeader(HttpHeaders.ETAG, pair.getKey().getEtag()) + .exposeHeaders() + .respond(HttpStatus.OK, pair.getValue())) .onFailure(error -> handleError(descriptor, error)); return Future.succeededFuture(); @@ -179,7 +176,7 @@ private void validateCustomApplication(Application application) { throw new HttpException(BAD_REQUEST, "No read access to file: " + file.getUrl()); }); } catch (ValidationException | IllegalArgumentException | ApplicationTypeSchemaValidationException e) { - throw new HttpException(BAD_REQUEST, " Custom application validation failed", e); + throw new HttpException(BAD_REQUEST, "Custom application validation failed", e); } catch (ApplicationTypeResourceException e) { throw new HttpException(FORBIDDEN, "Failed to access application resource " + e.getResourceUri(), e); } catch (ApplicationTypeSchemaProcessingException e) { @@ -236,11 +233,9 @@ private Future putResource(ResourceDescriptor descriptor) { }); } - responseFuture.onSuccess((metadata) -> { - context.putHeader(HttpHeaders.ETAG, metadata.getEtag()) - .exposeHeaders() - .respond(HttpStatus.OK, metadata); - }) + responseFuture.onSuccess((metadata) -> context.putHeader(HttpHeaders.ETAG, metadata.getEtag()) + .exposeHeaders() + .respond(HttpStatus.OK, metadata)) .onFailure(error -> handleError(descriptor, error)); return Future.succeededFuture(); diff --git a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java index 24af4461..62ee0609 100644 --- a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java +++ b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java @@ -33,6 +33,9 @@ public Boolean apply(ObjectNode tree) { if (!(deployment instanceof Application application && application.getApplicationTypeSchemaId() != null)) { return false; } + if (application.getApplicationProperties() == null) { + throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, "Typed application's properties not set"); + } List resources = ApplicationTypeSchemaUtils.getServerFiles(context.getConfig(), application, proxy.getEncryptionService(), proxy.getResourceService()); ApiKeyData keyData = context.getProxyApiKeyData(); diff --git a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java index 30742448..da4d78a2 100644 --- a/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java +++ b/server/src/main/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtils.java @@ -173,9 +173,6 @@ private static List getFiles(Config config, Application appl if (customApplicationSchema == null) { return Collections.emptyList(); } - if (application.getApplicationProperties() == null) { - throw new ApplicationTypeSchemaValidationException("Typed application's properties not set"); - } JsonSchema appSchema = SCHEMA_FACTORY.getSchema(customApplicationSchema); CollectorContext collectorContext = new CollectorContext(); String customPropsJson = ProxyUtil.MAPPER.writeValueAsString(application.getApplicationProperties()); From 8254522a8aee22dfe09971a4ac55d955674e7816 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 19:45:24 +0100 Subject: [PATCH 5/8] ApplicationTypeSchemaUtilsTest fixes to reflect ApplicationTypeResourceException cases --- .../util/ApplicationTypeSchemaUtilsTest.java | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java index 3de5b5f8..0343ff5b 100644 --- a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java @@ -6,6 +6,7 @@ import com.epam.aidial.core.server.ProxyContext; import com.epam.aidial.core.server.security.AccessService; import com.epam.aidial.core.server.security.EncryptionService; +import com.epam.aidial.core.server.validation.ApplicationTypeResourceException; import com.epam.aidial.core.server.validation.ApplicationTypeSchemaValidationException; import com.epam.aidial.core.storage.resource.ResourceDescriptor; import com.epam.aidial.core.storage.service.ResourceService; @@ -32,34 +33,35 @@ public class ApplicationTypeSchemaUtilsTest { private ResourceDescriptor resource; private AccessService accessService; - private final String schema = "{" - + "\"$schema\": \"https://dial.epam.com/application_type_schemas/schema#\"," - + "\"$id\": \"https://mydial.epam.com/custom_application_schemas/specific_application_type\"," - + "\"dial:applicationTypeEditorUrl\": \"https://mydial.epam.com/specific_application_type_editor\"," - + "\"dial:applicationTypeDisplayName\": \"Specific Application Type\"," - + "\"dial:applicationTypeCompletionEndpoint\": \"http://specific_application_service/opeani/v1/completion\"," - + "\"properties\": {" - + " \"clientFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"client\"," - + " \"dial:propertyOrder\": 1" - + " }," - + " \"dial:file\" : true" - + " }," - + " \"serverFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"server\"," - + " \"dial:propertyOrder\": 2" - + " }," - + " \"dial:file\" : true" - + " }" - + "}," - + "\"required\": [\"clientFile\",\"serverFile\"]" - + "}"; + private final String schema = """ + { + "$schema" : "https://dial.epam.com/application_type_schemas/schema#", + "$id" : "https://mydial.epam.com/custom_application_schemas/specific_application_type", + "dial:applicationTypeEditorUrl" : "https://mydial.epam.com/specific_application_type_editor", + "dial:applicationTypeDisplayName" : "Specific Application Type", + "dial:applicationTypeCompletionEndpoint" : "http://specific_application_service/opeani/v1/completion", + "properties" : { + "clientFile" : { + "type" : "string", + "format" : "dial-file-encoded", + "dial:meta" : { + "dial:propertyKind" : "client", + "dial:propertyOrder" : 1 + }, + "dial:file" : true + }, + "serverFile" : { + "type" : "string", + "format" : "dial-file-encoded", + "dial:meta" : { + "dial:propertyKind" : "server", + "dial:propertyOrder" : 2 + }, + "dial:file" : true + } + }, + "required" : [ "clientFile", "serverFile" ] + }"""; private final Map clientProperties = Map.of("clientFile", "files/public/valid-file-path/valid-sub-path/valid%20file%20name1.ext"); @@ -229,20 +231,20 @@ public void modifyEndpointForCustomApplication_throws_whenSchemaIsNull() { @Test public void modifyEndpointForCustomApplication_throws_whenEndpointNotFound() { String schemaWithoutEndpoint = "{" - + "\"$schema\": \"https://dial.epam.com/application_type_schemas/schema#\"," - + "\"$id\": \"https://mydial.epam.com/custom_application_schemas/specific_application_type\"," - + "\"properties\": {" - + " \"clientFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"client\"," - + " \"dial:propertyOrder\": 1" - + " }" - + " }" - + "}," - + "\"required\": [\"clientFile\"]" - + "}"; + + "\"$schema\": \"https://dial.epam.com/application_type_schemas/schema#\"," + + "\"$id\": \"https://mydial.epam.com/custom_application_schemas/specific_application_type\"," + + "\"properties\": {" + + " \"clientFile\": {" + + " \"type\": \"string\"," + + " \"format\": \"dial-file-encoded\"," + + " \"dial:meta\": {" + + " \"dial:propertyKind\": \"client\"," + + " \"dial:propertyOrder\": 1" + + " }" + + " }" + + "}," + + "\"required\": [\"clientFile\"]" + + "}"; application.setApplicationTypeSchemaId(URI.create("schemaId")); when(config.getCustomApplicationSchema(any())).thenReturn(schemaWithoutEndpoint); @@ -357,7 +359,7 @@ public void getFiles_throwsException_whenResourceNotFound() { when(resourceService.hasResource(any())).thenReturn(false); - Assertions.assertThrows(ApplicationTypeSchemaValidationException.class, () -> + Assertions.assertThrows(ApplicationTypeResourceException.class, () -> ApplicationTypeSchemaUtils.getFiles(config, application, encryptionService, resourceService)); } @@ -401,7 +403,7 @@ public void getServerFiles_throwsException_whenResourceNotFound() { when(resourceService.hasResource(any())).thenReturn(false); - Assertions.assertThrows(ApplicationTypeSchemaValidationException.class, () -> + Assertions.assertThrows(ApplicationTypeResourceException.class, () -> ApplicationTypeSchemaUtils.getServerFiles(config, application, encryptionService, resourceService)); } } From ffd4b8bfa9e6621031ff7dd09ebf0803b298ec32 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Mon, 20 Jan 2025 20:20:40 +0100 Subject: [PATCH 6/8] modifyEndpointForCustomApplication_throws_whenEndpointNotFound reformating --- .../util/ApplicationTypeSchemaUtilsTest.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java index 0343ff5b..81a06f88 100644 --- a/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/util/ApplicationTypeSchemaUtilsTest.java @@ -230,21 +230,22 @@ public void modifyEndpointForCustomApplication_throws_whenSchemaIsNull() { @Test public void modifyEndpointForCustomApplication_throws_whenEndpointNotFound() { - String schemaWithoutEndpoint = "{" - + "\"$schema\": \"https://dial.epam.com/application_type_schemas/schema#\"," - + "\"$id\": \"https://mydial.epam.com/custom_application_schemas/specific_application_type\"," - + "\"properties\": {" - + " \"clientFile\": {" - + " \"type\": \"string\"," - + " \"format\": \"dial-file-encoded\"," - + " \"dial:meta\": {" - + " \"dial:propertyKind\": \"client\"," - + " \"dial:propertyOrder\": 1" - + " }" - + " }" - + "}," - + "\"required\": [\"clientFile\"]" - + "}"; + String schemaWithoutEndpoint = """ + { + "$schema": "https://dial.epam.com/application_type_schemas/schema#", + "$id": "https://mydial.epam.com/custom_application_schemas/specific_application_type", + "properties": { + "clientFile": { + "type": "string", + "format": "dial-file-encoded", + "dial:meta": { + "dial:propertyKind": "client", + "dial:propertyOrder": 1 + } + } + }, + "required": ["clientFile"] + }"""; application.setApplicationTypeSchemaId(URI.create("schemaId")); when(config.getCustomApplicationSchema(any())).thenReturn(schemaWithoutEndpoint); From 115906401e7346106f81d96e76670962cb2e52d0 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Tue, 21 Jan 2025 11:15:35 +0100 Subject: [PATCH 7/8] moved assignPerRequestApiKey invocation to the end of a Fn chain --- .../server/controller/DeploymentPostController.java | 1 + .../function/CollectRequestApplicationFilesFn.java | 13 +++---------- .../function/CollectRequestAttachmentsFn.java | 3 --- .../CollectRequestApplicationFilesFnTest.java | 9 --------- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java b/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java index 9ed36b26..9415b8b7 100644 --- a/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java +++ b/server/src/main/java/com/epam/aidial/core/server/controller/DeploymentPostController.java @@ -269,6 +269,7 @@ void handleRequestBody(Buffer requestBody) { if (ProxyUtil.processChain(tree, enhancementFunctions)) { context.setRequestBody(Buffer.buffer(ProxyUtil.MAPPER.writeValueAsBytes(tree))); } + proxy.getApiKeyStore().assignPerRequestApiKey(context.getProxyApiKeyData()); } catch (Throwable e) { if (e instanceof HttpException httpException) { respond(httpException.getStatus(), httpException.getMessage()); diff --git a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java index 62ee0609..652ec272 100644 --- a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java +++ b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFn.java @@ -8,7 +8,6 @@ import com.epam.aidial.core.server.data.AutoSharedData; import com.epam.aidial.core.server.security.AccessService; import com.epam.aidial.core.server.util.ApplicationTypeSchemaUtils; -import com.epam.aidial.core.server.util.ProxyUtil; import com.epam.aidial.core.server.validation.ApplicationTypeResourceException; import com.epam.aidial.core.storage.data.ResourceAccessType; import com.epam.aidial.core.storage.http.HttpException; @@ -38,14 +37,7 @@ public Boolean apply(ObjectNode tree) { } List resources = ApplicationTypeSchemaUtils.getServerFiles(context.getConfig(), application, proxy.getEncryptionService(), proxy.getResourceService()); - ApiKeyData keyData = context.getProxyApiKeyData(); - appendFilesToProxyApiKeyData(keyData, resources); - String perRequestKey = keyData.getPerRequestKey(); - if (perRequestKey == null) { //This class may be not the one who modifies the perRequestKey - proxy.getApiKeyStore().assignPerRequestApiKey(keyData); - } else { - proxy.getApiKeyStore().updatePerRequestApiKey(perRequestKey, json -> ProxyUtil.convertToString(keyData)); - } + appendFilesToProxyApiKeyData(resources); return false; } catch (HttpException ex) { throw ex; @@ -56,7 +48,8 @@ public Boolean apply(ObjectNode tree) { } } - private void appendFilesToProxyApiKeyData(ApiKeyData apiKeyData, List resources) { + private void appendFilesToProxyApiKeyData(List resources) { + ApiKeyData apiKeyData = context.getProxyApiKeyData(); for (ResourceDescriptor resource : resources) { String resourceUrl = resource.getUrl(); AccessService accessService = proxy.getAccessService(); diff --git a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestAttachmentsFn.java b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestAttachmentsFn.java index 420a538f..d4981d80 100644 --- a/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestAttachmentsFn.java +++ b/server/src/main/java/com/epam/aidial/core/server/function/CollectRequestAttachmentsFn.java @@ -28,9 +28,6 @@ public CollectRequestAttachmentsFn(Proxy proxy, ProxyContext context) { @Override public Boolean apply(ObjectNode tree) { ProxyUtil.collectAttachedFilesFromRequest(tree, this::processAttachedFile); - // assign api key data after processing attachments - ApiKeyData destApiKeyData = context.getProxyApiKeyData(); - proxy.getApiKeyStore().assignPerRequestApiKey(destApiKeyData); return false; } diff --git a/server/src/test/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFnTest.java b/server/src/test/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFnTest.java index bacbe119..adeee9bb 100644 --- a/server/src/test/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFnTest.java +++ b/server/src/test/java/com/epam/aidial/core/server/function/CollectRequestApplicationFilesFnTest.java @@ -7,12 +7,10 @@ import com.epam.aidial.core.server.ProxyContext; import com.epam.aidial.core.server.data.ApiKeyData; import com.epam.aidial.core.server.security.AccessService; -import com.epam.aidial.core.server.security.ApiKeyStore; import com.epam.aidial.core.storage.http.HttpException; import com.epam.aidial.core.storage.service.ResourceService; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.vertx.core.Vertx; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -53,10 +51,6 @@ public class CollectRequestApplicationFilesFnTest { @Mock private ResourceService resourceService; - private ApiKeyStore apiKeyStore; - - @Mock - private Vertx vertx; @InjectMocks private CollectRequestApplicationFilesFn fn; @@ -100,7 +94,6 @@ public class CollectRequestApplicationFilesFnTest { void setUp() { application = new Application(); tree = JsonNodeFactory.instance.objectNode(); - apiKeyStore = new ApiKeyStore(resourceService, vertx); } @Test @@ -127,7 +120,6 @@ void apply_doesNotAppendsFilesToApiKeyData_whenApplicationHasNoCustomSchemaId() void apply_appendsFilesToApiKeyData_whenApplicationHasCustomSchemaId() { when(proxy.getAccessService()).thenReturn(accessService); when(proxy.getResourceService()).thenReturn(resourceService); - when(proxy.getApiKeyStore()).thenReturn(apiKeyStore); when(context.getProxyApiKeyData()).thenReturn(new ApiKeyData()); when(context.getConfig()).thenReturn(config); String serverFile = "files/public/valid-file-path/valid-sub-path/valid%20file%20name2.ext"; @@ -147,7 +139,6 @@ void apply_appendsFilesToApiKeyData_whenApplicationHasCustomSchemaId() { assertFalse(result); assertNotNull(apiKeyData.getAttachedFiles().get(serverFile)); - assertNotNull(apiKeyData.getPerRequestKey()); assertEquals(1, apiKeyData.getAttachedFiles().size()); } From 69116f09baf01f4617005fdede108d0684daeb53 Mon Sep 17 00:00:00 2001 From: Sergey Zinchenko Date: Tue, 21 Jan 2025 13:28:51 +0100 Subject: [PATCH 8/8] doc --- .../server/validation/ApplicationTypeResourceException.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java index fbc660d9..1fdd093b 100644 --- a/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java +++ b/server/src/main/java/com/epam/aidial/core/server/validation/ApplicationTypeResourceException.java @@ -2,6 +2,12 @@ import lombok.Getter; + +/** + * Exception thrown when there is an issue with a resource associated with an application type. + * This exception is typically used when a resource listed as dependent to the application + * is not found, inaccessible, or there is a failure in obtaining the resource descriptor. + */ @Getter public class ApplicationTypeResourceException extends RuntimeException {