Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.epam.aidial.core.config.ResourceAccessType;
import com.epam.aidial.core.config.ResourceAuthSettings;
import com.epam.aidial.core.config.Route;
import com.epam.aidial.core.credentials.data.credentials.CredentialsLocator;
import com.epam.aidial.core.credentials.service.ResourceAuthSettingsService;
import com.epam.aidial.core.metaschemas.MetaSchemaHolder;
import com.epam.aidial.core.openapi.annotations.ApiOperation;
Expand All @@ -28,8 +27,8 @@
import com.epam.aidial.core.server.service.ApplicationSchemaService;
import com.epam.aidial.core.server.service.ApplicationService;
import com.epam.aidial.core.server.service.DeploymentService;
import com.epam.aidial.core.server.service.ExternalServiceStatusEnricher;
import com.epam.aidial.core.server.service.PermissionDeniedException;
import com.epam.aidial.core.server.service.ResourceAuthStatusEnricher;
import com.epam.aidial.core.server.service.UserExternalServiceService;
import com.epam.aidial.core.server.util.CredentialsLocatorFactory;
import com.epam.aidial.core.server.util.ProxyUtil;
Expand All @@ -40,6 +39,7 @@
import com.epam.aidial.core.storage.http.HttpStatus;
import com.epam.aidial.core.storage.resource.ResourceDescriptor;
import com.epam.aidial.core.storage.resource.ResourceTypes;
import com.epam.aidial.core.storage.util.UrlUtil;
import io.vertx.core.Future;
import lombok.extern.slf4j.Slf4j;

Expand Down Expand Up @@ -114,7 +114,8 @@ public Future<?> getApplication(String applicationId) {
// sign-in status (one credential lookup per service). The listing skips both to avoid
// N×M lookups — it returns the inline definitions only.
overlayUserAuthoredServices(data, application);
enrichExternalServiceStatuses(data);
new ResourceAuthStatusEnricher(context, resourceAuthSettingsService)
.enrichApplication(UrlUtil.tryDecodePath(data.getId()), data.getExternalServices());
return data;
})
.onSuccess(data -> context.respond(HttpStatus.OK, data))
Expand Down Expand Up @@ -465,27 +466,4 @@ private static String appPart(String id) {
? id.substring(CredentialsLocatorFactory.APPLICATIONS_PREFIX.length()) : id;
}

private void enrichExternalServiceStatuses(ApplicationData data) {
Map<String, ExternalService> services = data.getExternalServices();
if (services == null || services.isEmpty()) {
return;
}
String appId = appPart(data.getId());
ExternalServiceStatusEnricher enricher = new ExternalServiceStatusEnricher(context, resourceAuthSettingsService);
for (Map.Entry<String, ExternalService> entry : services.entrySet()) {
ResourceAuthSettings authSettings = entry.getValue().getAuthSettings();
if (authSettings == null) {
continue;
}
try {
String scopeId = CredentialsLocatorFactory.APPLICATIONS_PREFIX + appId
+ CredentialsLocatorFactory.EXTERNAL_SERVICES_SEPARATOR + entry.getKey();
CredentialsLocator locator = CredentialsLocatorFactory.fromExternalServiceScope(scopeId, context);
enricher.enrich(locator, authSettings);
} catch (RuntimeException e) {
log.warn("Failed to compute external-service status for '{}' on '{}'", entry.getKey(), data.getId(), e);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.epam.aidial.core.config.Route;
import com.epam.aidial.core.config.ToolSet;
import com.epam.aidial.core.config.Translator;
import com.epam.aidial.core.credentials.service.ResourceAuthSettingsService;
import com.epam.aidial.core.openapi.annotations.ApiExtension;
import com.epam.aidial.core.openapi.annotations.ApiHeader;
import com.epam.aidial.core.openapi.annotations.ApiOperation;
Expand All @@ -20,6 +21,7 @@
import com.epam.aidial.core.openapi.annotations.ApiSchema;
import com.epam.aidial.core.openapi.annotations.OpenApiDescriptions;
import com.epam.aidial.core.openapi.annotations.ParameterIn;
import com.epam.aidial.core.server.Proxy;
import com.epam.aidial.core.server.ProxyContext;
import com.epam.aidial.core.server.config.ConfigPostProcessor;
import com.epam.aidial.core.server.config.InvalidEntityRecord;
Expand All @@ -34,6 +36,7 @@
import com.epam.aidial.core.server.security.Operation;
import com.epam.aidial.core.server.service.AdminManagedFieldsWriteMode;
import com.epam.aidial.core.server.service.ApplicationService;
import com.epam.aidial.core.server.service.ResourceAuthStatusEnricher;
import com.epam.aidial.core.server.service.ToolSetService;
import com.epam.aidial.core.server.service.config.ConfigEntityCodec;
import com.epam.aidial.core.server.util.ProxyUtil;
Expand Down Expand Up @@ -101,35 +104,28 @@ public class ConfigResourceController implements Controller {
private final LockService lockService;
private final ApplicationService applicationService;
private final ToolSetService toolSetService;
private final ResourceAuthSettingsService resourceAuthSettingsService;
private final String entityType;
private final String bucket;
private final String path;

public ConfigResourceController(ProxyContext context,
ConfigAuthorizationService authorizationService,
MergedConfigStore mergedConfigStore,
ResourceService resourceService,
AsyncTaskExecutor taskExecutor,
SecretFieldProcessor secretFieldProcessor,
boolean softValidation,
ApiKeyStore apiKeyStore,
LockService lockService,
ApplicationService applicationService,
ToolSetService toolSetService,
public ConfigResourceController(Proxy proxy,
ProxyContext context,
String entityType,
String bucket,
String path) {
this.context = context;
this.authorizationService = authorizationService;
this.mergedConfigStore = mergedConfigStore;
this.resourceService = resourceService;
this.taskExecutor = taskExecutor;
this.secretFieldProcessor = secretFieldProcessor;
this.softValidation = softValidation;
this.apiKeyStore = apiKeyStore;
this.lockService = lockService;
this.applicationService = applicationService;
this.toolSetService = toolSetService;
this.authorizationService = proxy.getConfigAuthService();
this.mergedConfigStore = (MergedConfigStore) proxy.getConfigStore();
this.resourceService = proxy.getResourceService();
this.taskExecutor = proxy.getTaskExecutor();
this.secretFieldProcessor = mergedConfigStore.getSecretFieldProcessor();
this.softValidation = mergedConfigStore.isSoftValidation();
this.apiKeyStore = proxy.getApiKeyStore();
this.lockService = proxy.getLockService();
this.applicationService = proxy.getApplicationService();
this.toolSetService = proxy.getToolSetService();
this.resourceAuthSettingsService = proxy.getResourceAuthSettingsService();
this.entityType = entityType;
this.bucket = bucket;
this.path = path;
Expand Down Expand Up @@ -1119,19 +1115,24 @@ private Future<?> handleGet() {
// actually be shown the hint.
case APPLICATION -> handleSingleGetFromBlob(ResourceTypes.APPLICATION,
(key, application) -> {
Application entity = (Application) application;
new ResourceAuthStatusEnricher(context, resourceAuthSettingsService)
.enrichApplication(path, entity.getExternalServices());
if (admin) {
applicationService.decryptExternalServiceSecretsForResponse(
descriptorFor(ResourceTypes.APPLICATION), (Application) application);
descriptorFor(ResourceTypes.APPLICATION), entity);
}
return redactExternalServiceSecrets(projectItem(application, key), admin);
return redactExternalServiceSecrets(projectItem(entity, key), admin);
});
case TOOL_SET -> handleSingleGetFromBlob(ResourceTypes.TOOL_SET,
(key, toolSet) -> {
ToolSet entity = (ToolSet) toolSet;
new ResourceAuthStatusEnricher(context, resourceAuthSettingsService).enrichToolSet(path, entity);
if (admin) {
toolSetService.decryptAuthSettingsForResponse(
descriptorFor(ResourceTypes.TOOL_SET), (ToolSet) toolSet);
descriptorFor(ResourceTypes.TOOL_SET), entity);
}
return redactAuthSettingsSecrets(projectItem(toolSet, key), admin);
return redactAuthSettingsSecrets(projectItem(entity, key), admin);
});
case GLOBAL_SETTINGS -> handleSettingsGet(config);
default -> respondMethodNotAllowed();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -665,17 +665,7 @@ private static Controller configResourceController(Proxy proxy, ProxyContext con
// FILES/RESOURCE routes (see ResourceDescriptorFactory.fromAnyUrl) and the {@code path}
// contract on ResourceDescriptorFactory.fromDecoded ("url decoded relative path").
String path = UrlUtil.decodePath(pathMatcher.group("path"));
ConfigAuthorizationService authService = new AdminRoleAuthorizationService(proxy.getAccessService());
MergedConfigStore mergedConfigStore = (MergedConfigStore) proxy.getConfigStore();
return new ConfigResourceController(context, authService, mergedConfigStore,
proxy.getResourceService(), proxy.getTaskExecutor(),
mergedConfigStore.getSecretFieldProcessor(),
mergedConfigStore.isSoftValidation(),
proxy.getApiKeyStore(),
proxy.getLockService(),
proxy.getApplicationService(),
proxy.getToolSetService(),
entityType, bucket, path);
return new ConfigResourceController(proxy, context, entityType, bucket, path);
}

private static Controller configResourceMetadataController(Proxy proxy, ProxyContext context, Matcher pathMatcher) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import com.epam.aidial.core.server.security.EncryptionService;
import com.epam.aidial.core.server.service.ApplicationService;
import com.epam.aidial.core.server.service.ExternalServiceService;
import com.epam.aidial.core.server.service.ExternalServiceStatusEnricher;
import com.epam.aidial.core.server.service.PermissionDeniedException;
import com.epam.aidial.core.server.service.ResourceAuthStatusEnricher;
import com.epam.aidial.core.server.service.UserExternalServiceService;
import com.epam.aidial.core.server.util.CredentialsLocatorFactory;
import com.epam.aidial.core.server.util.ProxyUtil;
Expand Down Expand Up @@ -61,7 +61,7 @@ public class ExternalServiceManagementController {
private final EncryptionService encryptionService;
private final ResourceCredentialsService resourceCredentialsService;
private final ResourceAuthSettingsService resourceAuthSettingsService;
private final ExternalServiceStatusEnricher statusEnricher;
private final ResourceAuthStatusEnricher statusEnricher;

public ExternalServiceManagementController(Proxy proxy, ProxyContext context) {
this.context = context;
Expand All @@ -73,7 +73,7 @@ public ExternalServiceManagementController(Proxy proxy, ProxyContext context) {
this.encryptionService = proxy.getEncryptionService();
this.resourceCredentialsService = proxy.getResourceCredentialsService();
this.resourceAuthSettingsService = proxy.getResourceAuthSettingsService();
this.statusEnricher = new ExternalServiceStatusEnricher(context, resourceAuthSettingsService);
this.statusEnricher = new ResourceAuthStatusEnricher(context, resourceAuthSettingsService);
}

@ApiOperation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.epam.aidial.core.config.Features;
import com.epam.aidial.core.config.ResourceAuthSettings;
import com.epam.aidial.core.config.ToolSet;
import com.epam.aidial.core.credentials.data.credentials.CredentialsLocator;
import com.epam.aidial.core.openapi.annotations.ApiHeader;
import com.epam.aidial.core.openapi.annotations.ApiOperation;
import com.epam.aidial.core.openapi.annotations.ApiOperations;
Expand All @@ -24,9 +23,9 @@
import com.epam.aidial.core.server.service.ApplicationSchemaService;
import com.epam.aidial.core.server.service.ApplicationService;
import com.epam.aidial.core.server.service.DeploymentService;
import com.epam.aidial.core.server.service.ExternalServiceStatusEnricher;
import com.epam.aidial.core.server.service.ExternalServicesWriteMode;
import com.epam.aidial.core.server.service.PermissionDeniedException;
import com.epam.aidial.core.server.service.ResourceAuthStatusEnricher;
import com.epam.aidial.core.server.service.ToolSetService;
import com.epam.aidial.core.server.util.ApplicationTypeSchemaProcessingException;
import com.epam.aidial.core.server.util.CredentialsLocatorFactory;
Expand Down Expand Up @@ -55,7 +54,6 @@
import java.net.ConnectException;
import java.net.http.HttpConnectTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
Expand Down Expand Up @@ -564,7 +562,8 @@ private Future<Pair<ResourceItemMetadata, String>> getApplicationData(ResourceDe
proxy.getExternalServiceService().decryptSecretsForResponse(descriptor, application);
}
overlayUserAuthoredServices(descriptor, application);
enrichExternalServiceStatuses(descriptor, application);
new ResourceAuthStatusEnricher(context, proxy.getResourceAuthSettingsService())
.enrichApplication(descriptor.getDecodedUrl(), application.getExternalServices());
clearExternalServiceSecrets(application, hasWriteAccess);

if (!accessService.hasAdminAccess(context)) {
Expand All @@ -591,28 +590,6 @@ private void overlayUserAuthoredServices(ResourceDescriptor descriptor, Applicat
application.setExternalServices(merged);
}

private void enrichExternalServiceStatuses(ResourceDescriptor descriptor, Application application) {
Map<String, ExternalService> services = application.getExternalServices();
if (services == null || services.isEmpty()) {
return;
}
ExternalServiceStatusEnricher enricher = new ExternalServiceStatusEnricher(
context, proxy.getResourceAuthSettingsService());
for (Map.Entry<String, ExternalService> entry : services.entrySet()) {
ResourceAuthSettings authSettings = entry.getValue() == null ? null : entry.getValue().getAuthSettings();
if (authSettings == null) {
continue;
}
try {
String scopeId = descriptor.getUrl() + CredentialsLocatorFactory.EXTERNAL_SERVICES_SEPARATOR + entry.getKey();
CredentialsLocator locator = CredentialsLocatorFactory.fromExternalServiceScope(scopeId, context);
enricher.enrich(locator, authSettings);
} catch (RuntimeException e) {
log.warn("Failed to compute external-service status for '{}' on '{}'", entry.getKey(), descriptor.getUrl(), e);
}
}
}

private static void clearExternalServiceSecrets(Application application, boolean hasWriteAccess) {
Map<String, ExternalService> services = application.getExternalServices();
if (services == null) {
Expand Down Expand Up @@ -669,7 +646,8 @@ private Future<Pair<ResourceItemMetadata, String>> getToolsetData(ResourceDescri
Pair<ResourceItemMetadata, ToolSet> result = toolSetService.getToolSet(descriptor, etagHeader);
ResourceItemMetadata meta = result.getKey();
ToolSet toolSet = result.getValue();
toolSetService.setResourceAuthStatuses(context, toolSet, descriptor.getUrl());
new ResourceAuthStatusEnricher(context, proxy.getResourceAuthSettingsService())
.enrichToolSet(descriptor.getDecodedUrl(), toolSet);
toolSetService.redactAuthSettings(descriptor, toolSet, hasWriteAccess);
if (!hasWriteAccess) {
toolSet.setEndpoint(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.epam.aidial.core.server.data.ToolSetData;
import com.epam.aidial.core.server.service.DeploymentService;
import com.epam.aidial.core.server.service.PermissionDeniedException;
import com.epam.aidial.core.server.service.ResourceAuthStatusEnricher;
import com.epam.aidial.core.server.service.ToolSetService;
import com.epam.aidial.core.server.vertx.AsyncTaskExecutor;
import com.epam.aidial.core.storage.data.ResourceItemMetadata;
Expand Down Expand Up @@ -66,8 +67,8 @@ public Future<?> getToolSet(String toolSetId) {
taskExecutor.submit(() -> {
Deployment deployment = deploymentService.findDeployment(context, toolSetId);
if (deployment instanceof ToolSet toolSet) {
String encodedToolSetId = UrlUtil.encodePath(toolSetId);
toolSetService.setResourceAuthStatuses(context, toolSet, encodedToolSetId);
new ResourceAuthStatusEnricher(context, context.getProxy().getResourceAuthSettingsService())
.enrichToolSet(toolSetId, toolSet);
return toolSet;
}
throw new ResourceNotFoundException("Toolset is not found: " + toolSetId);
Expand Down Expand Up @@ -101,10 +102,12 @@ public Future<?> getToolSets() {
}

private List<ToolSet> mergeToolsets(List<ToolSet> resourceToolsets, Config config) {
ResourceAuthStatusEnricher enricher =
new ResourceAuthStatusEnricher(context, context.getProxy().getResourceAuthSettingsService());
List<ToolSet> list = new ArrayList<>();
for (ToolSet toolSet : config.getToolsets().values()) {
if (toolSet.hasAccess(context.getUserRoles())) {
toolSetService.setResourceAuthStatuses(context, toolSet, toolSet.getName());
enricher.enrichToolSet(UrlUtil.tryDecodePath(toolSet.getName()), toolSet);
list.add(toolSet);
}
}
Expand Down Expand Up @@ -139,9 +142,11 @@ private Void updateAuthStatus(int start, int end, List<ToolSet> toolSets) {
if (end - start <= 0) {
return null;
}
ResourceAuthStatusEnricher enricher =
new ResourceAuthStatusEnricher(context, context.getProxy().getResourceAuthSettingsService());
for (int i = start; i < end; i++) {
ToolSet toolSet = toolSets.get(i);
toolSetService.setResourceAuthStatuses(context, toolSet, toolSet.getName());
enricher.enrichToolSet(UrlUtil.tryDecodePath(toolSet.getName()), toolSet);
}
return null;
}
Expand Down
Loading