mabel/src/routes/sites.rs

116 lines
3.1 KiB
Rust

use axum::{
extract::Path,
response::IntoResponse,
routing::{get, post},
Json, Router,
};
use serde_json::json;
use std::sync::Arc;
use crate::{
content::{
collection::CollectionRepository,
site::{CreateSiteData, SiteRepository, UpdateSiteData},
},
database::Database,
http::{error::ApiError, json::JsonBody, session::RequireUser},
state::AppState,
};
/// Retrieve site info/metadata
#[utoipa::path(
get,
path = "/sites/{site}",
params(
("site" = String, Path, description = "Site slug")
),
responses(
(status = 200, description = "Site info found", body = SiteData),
(status = 404, description = "Site not found")
)
)]
pub(super) async fn get_site<Repo: SiteRepository>(
repository: Repo,
Path(name): Path<String>,
) -> Result<impl IntoResponse, ApiError<'static>> {
Ok(Json(repository.get_site_by_name(&name).await?))
}
/// Create a new site
#[utoipa::path(
post,
path = "/sites",
request_body = CreateSiteData,
responses(
(status = 200, description = "Site created"),
(status = 409, description = "The chosen site identifier/slug is not available")
)
)]
pub(super) async fn create_site<Repo: SiteRepository + CollectionRepository>(
repository: Repo,
RequireUser(user): RequireUser,
JsonBody(options): JsonBody<CreateSiteData>,
) -> Result<impl IntoResponse, ApiError<'static>> {
let id = repository.create_site(&user.id, options).await?;
// Create default content for the new site
repository.create_default_collections(&id).await?;
Ok(Json(json!({"ok": true})))
}
/// Update an existing site's info
#[utoipa::path(
put,
path = "/sites/{site}",
params(
("site" = String, Path, description = "Site slug")
),
request_body = UpdateSiteData,
responses(
(status = 200, description = "Site updated"),
(status = 404, description = "Site not found")
)
)]
pub(super) async fn update_site<Repo: SiteRepository>(
repository: Repo,
Path(name): Path<String>,
RequireUser(user): RequireUser,
JsonBody(options): JsonBody<UpdateSiteData>,
) -> Result<impl IntoResponse, ApiError<'static>> {
repository.update_site(&user.id, &name, options).await?;
Ok(Json(json!({"ok": true})))
}
/// Delete an existing site
#[utoipa::path(
delete,
path = "/sites/{site}",
params(
("site" = String, Path, description = "Site slug")
),
responses(
(status = 200, description = "Site deleted"),
(status = 404, description = "Site not found")
)
)]
pub(super) async fn delete_site<Repo: SiteRepository>(
repository: Repo,
Path(name): Path<String>,
RequireUser(user): RequireUser,
) -> Result<impl IntoResponse, ApiError<'static>> {
repository.delete_site(&user.id, &name, true).await?;
Ok(Json(json!({"ok": true})))
}
pub(super) fn router() -> Router<Arc<AppState>> {
Router::new()
.route("/", post(create_site::<Database>))
.route(
"/:name",
get(get_site::<Database>)
.put(update_site::<Database>)
.delete(delete_site::<Database>),
)
}