use axum::body::Bytes;
use axum::extract::State;
use axum::http::header::CONTENT_TYPE;
use axum::http::{HeaderMap, StatusCode};
use axum::response::{IntoResponse, Response};
use axum::{Extension, Json};
use sbol_db_app::PluginError;
use serde::Deserialize;
use serde_json::Value;
use super::{parse_body, CurrentUser};
use crate::AppState;
fn is_admin(user: &Option<sbol_db_core::User>) -> bool {
user.as_ref().map(|u| u.is_admin).unwrap_or(false)
}
fn text(status: StatusCode, body: impl Into<String>) -> Response {
(status, [(CONTENT_TYPE, "text/plain")], body.into()).into_response()
}
fn plugin_error(err: PluginError) -> Response {
let (status, message) = match err {
PluginError::NotAuthorized => (StatusCode::FORBIDDEN, err.to_string()),
PluginError::MissingField(m) => (StatusCode::BAD_REQUEST, m),
PluginError::NotFound(m) => (StatusCode::NOT_FOUND, m),
PluginError::Contact(m) => (StatusCode::INTERNAL_SERVER_ERROR, m),
PluginError::Domain(d) => (StatusCode::INTERNAL_SERVER_ERROR, d.to_string()),
};
text(status, message)
}
pub async fn plugins(State(state): State<AppState>) -> Response {
match state.app.plugins().plugins().await {
Ok(map) => Json(Value::Object(map)).into_response(),
Err(e) => plugin_error(PluginError::Domain(e)),
}
}
#[derive(Debug, Default, Deserialize)]
struct SavePluginForm {
#[serde(default)]
category: String,
#[serde(default = "default_id")]
id: String,
#[serde(default)]
name: String,
#[serde(default)]
url: String,
}
fn default_id() -> String {
"New".to_owned()
}
pub async fn save_plugin(
State(state): State<AppState>,
Extension(CurrentUser(user)): Extension<CurrentUser>,
headers: HeaderMap,
body: Bytes,
) -> Response {
let form: SavePluginForm = match parse_body(&headers, &body) {
Ok(f) => f,
Err(e) => return text(StatusCode::BAD_REQUEST, e.to_string()),
};
match state
.app
.plugins()
.save_plugin(
is_admin(&user),
&form.category,
&form.id,
&form.name,
&form.url,
)
.await
{
Ok(name) => text(
StatusCode::OK,
format!(
"Plugin ({}, {}, {}, {}) saved successfully",
form.id, name, form.url, form.category
),
),
Err(e) => plugin_error(e),
}
}
#[derive(Debug, Default, Deserialize)]
struct DeletePluginForm {
#[serde(default)]
category: String,
#[serde(default)]
id: String,
}
pub async fn delete_plugin(
State(state): State<AppState>,
Extension(CurrentUser(user)): Extension<CurrentUser>,
headers: HeaderMap,
body: Bytes,
) -> Response {
let form: DeletePluginForm = match parse_body(&headers, &body) {
Ok(f) => f,
Err(e) => return text(StatusCode::BAD_REQUEST, e.to_string()),
};
match state
.app
.plugins()
.delete_plugin(is_admin(&user), &form.category, &form.id)
.await
{
Ok(()) => text(
StatusCode::OK,
format!(
"Plugin ({}, {}) deleted successfully",
form.id, form.category
),
),
Err(e) => plugin_error(e),
}
}