use crate::models::{Adapters, V1UserProfile};
use crate::state::AppState;
use axum::{
extract::Extension, extract::Json, extract::Path, extract::State, http::StatusCode,
response::IntoResponse,
};
use serde_json::json;
use tracing::info;
#[axum::debug_handler]
pub async fn list_adapters(
State(state): State<AppState>,
Extension(user_profile): Extension<V1UserProfile>,
) -> impl IntoResponse {
let mut owners = Vec::new();
owners.push(user_profile.email.clone());
let organization_ids: Vec<String> = if let Some(orgs) = &user_profile.organizations {
orgs.keys().cloned().collect()
} else {
Vec::new()
};
owners.extend(organization_ids);
let mut adapters = Vec::new();
for owner in owners {
let adapters_path = format!("/orign/{}/adapters", owner);
match tokio::fs::read_dir(&adapters_path).await {
Ok(mut dir) => {
while let Ok(Some(entry)) = dir.next_entry().await {
let file_type = match entry.file_type().await {
Ok(ft) => ft,
Err(err) => {
return Err((
StatusCode::INTERNAL_SERVER_ERROR,
format!("Failed to get file type: {}", err),
));
}
};
if file_type.is_dir() {
if let Some(name) = entry.file_name().to_str() {
let resolved_owner = if owner == user_profile.email {
user_profile
.handle
.clone()
.unwrap_or(user_profile.email.clone())
} else {
user_profile
.organizations
.as_ref()
.and_then(|orgs| orgs.get(&owner))
.and_then(|org_data| org_data.get("org_name"))
.cloned()
.unwrap_or(owner.clone())
};
adapters.push(format!("{}/{}", resolved_owner, name));
}
}
}
}
Err(_) => {
continue;
}
}
}
Ok(Json(Adapters { adapters }))
}
fn resolve_namespace_owner(
namespace: &str,
user_profile: &V1UserProfile,
) -> Result<String, (StatusCode, String)> {
if let Some(ref handle) = user_profile.handle {
if handle == namespace {
return Ok(user_profile.email.clone());
}
}
if let Some(ref orgs) = user_profile.organizations {
let found = orgs.iter().find_map(|(org_id, org_data)| {
if let Some(org_name) = org_data.get("org_name") {
if org_name == namespace {
return Some(org_id.clone());
}
}
None
});
if let Some(org_id) = found {
return Ok(org_id);
}
}
Err((
StatusCode::FORBIDDEN,
format!(
"You do not have permission over the namespace '{}'",
namespace
),
))
}
#[axum::debug_handler]
pub async fn delete_adapter(
Path((namespace, adapter_name)): Path<(String, String)>,
State(state): State<AppState>,
Extension(user_profile): Extension<V1UserProfile>,
) -> impl IntoResponse {
let resolved_owner = match resolve_namespace_owner(&namespace, &user_profile) {
Ok(owner) => owner,
Err(err) => return Err(err),
};
let adapter_dir = format!("/{}/adapters/{}", resolved_owner, adapter_name);
info!("Deleting adapter directory: {:?}", &adapter_dir);
match tokio::fs::remove_dir_all(&adapter_dir).await {
Ok(_) => {
info!("Successfully removed adapter directory: {}", adapter_dir);
Ok(Json(json!({
"status": "ok",
"message": format!("Adapter '{}' successfully deleted from namespace '{}'", adapter_name, namespace),
})))
}
Err(e) => {
let msg = format!(
"Failed to remove adapter directory '{}': {}",
adapter_dir, e
);
info!("{}", msg);
Err((StatusCode::INTERNAL_SERVER_ERROR, msg))
}
}
}