use std::path::{Path, PathBuf};
use serde_json::json;
use crate::configuration::{BundleConfiguration, load_bundle_configuration};
use super::super::authorization::{
AuthorizationContext, authorize_route, load_authorization_context,
};
use super::super::connection::BundleCatalog;
use super::super::routing::{OperationProfile, ResolvedRoute};
use super::super::{GLOBAL_NAMESPACE, RelayError, RelayResponse, map_config, relay_error};
pub(super) fn run_target_operation<Prepared>(
home_namespace: &str,
authorization: &AuthorizationContext,
profile: OperationProfile,
resolve: impl FnOnce() -> Result<ResolvedRoute, RelayError>,
prepare: impl FnOnce(&ResolvedRoute) -> Result<Prepared, RelayError>,
execute: impl FnOnce(&ResolvedRoute, Prepared) -> Result<RelayResponse, RelayError>,
) -> Result<RelayResponse, RelayError> {
let route = resolve()?;
let prepared = prepare(&route)?;
authorize_route(home_namespace, authorization, profile, &route)?;
execute(&route, prepared)
}
pub(super) fn load_home_context(
home_namespace: &str,
configuration_root: &Path,
) -> Result<(Option<BundleConfiguration>, AuthorizationContext), RelayError> {
let home_bundle = if home_namespace == GLOBAL_NAMESPACE {
None
} else {
Some(load_bundle_configuration(configuration_root, home_namespace).map_err(map_config)?)
};
let authorization = load_authorization_context(configuration_root, home_bundle.as_ref())?;
Ok((home_bundle, authorization))
}
pub(super) fn resolve_target_bundle(
home_namespace: &str,
home_bundle: Option<&BundleConfiguration>,
home_runtime_directory: Option<&Path>,
target_namespace: &str,
configuration_root: &Path,
bundle_catalog: &BundleCatalog,
) -> Result<(BundleConfiguration, PathBuf), RelayError> {
if target_namespace == home_namespace
&& let Some(home_bundle) = home_bundle
{
let runtime = home_runtime_directory
.map(Path::to_path_buf)
.unwrap_or_default();
return Ok((home_bundle.clone(), runtime));
}
let Some(paths) = bundle_catalog.lookup(target_namespace) else {
return Err(relay_error(
"validation_unknown_bundle",
"target bundle is not configured on this relay",
Some(json!({ "bundle_name": target_namespace })),
));
};
let bundle =
load_bundle_configuration(configuration_root, target_namespace).map_err(map_config)?;
Ok((bundle, paths.runtime_directory.clone()))
}