Files
komodo/core/src/api/server.rs
2022-11-24 23:39:00 -08:00

120 lines
3.5 KiB
Rust

use anyhow::{anyhow, Context};
use async_timing_util::unix_timestamp_ms;
use axum::{
extract::Path,
routing::{get, post},
Extension, Json, Router,
};
use db::DbExtension;
use helpers::handle_anyhow_error;
use mungos::Deserialize;
use types::{Operation, PermissionLevel, Server, SystemStats, Update, UpdateTarget};
use crate::{auth::RequestUserExtension, helpers::get_user_permissions, ws::update};
use super::{add_update, PeripheryExtension};
pub fn router() -> Router {
Router::new()
.route(
"/list",
get(|db, user| async { list(db, user).await.map_err(handle_anyhow_error) }),
)
.route(
"/create",
post(|db, user, update_ws, server| async {
create(db, user, update_ws, server)
.await
.map_err(handle_anyhow_error)
}),
)
.route(
"/stats/:server_id",
get(|db, user, periphery, path| async {
stats(db, user, periphery, path)
.await
.map_err(handle_anyhow_error)
}),
)
}
async fn list(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
) -> anyhow::Result<Json<Vec<Server>>> {
let mut servers: Vec<Server> = db
.servers
.get_some(None, None)
.await
.context("failed at get all servers query")?
.into_iter()
.filter(|s| {
if user.is_admin {
true
} else {
let permissions = *s
.permissions
.get(&user.id)
.unwrap_or(&PermissionLevel::None);
permissions != PermissionLevel::None
}
})
.collect();
servers.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
Ok(Json(servers))
}
async fn create(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Extension(update_ws): update::UpdateWsSenderExtension,
Json(mut server): Json<Server>,
) -> anyhow::Result<()> {
server.permissions = [(user.id.clone(), PermissionLevel::Write)]
.into_iter()
.collect();
let start_ts = unix_timestamp_ms() as i64;
let server_id = db
.servers
.create_one(server)
.await
.context("failed to add server to db")?;
let update = Update {
target: UpdateTarget::Server(server_id),
operation: Operation::CreateServer,
start_ts,
end_ts: Some(unix_timestamp_ms() as i64),
operator: user.id.clone(),
..Default::default()
};
add_update(update, &db, &update_ws).await
}
#[derive(Deserialize)]
struct GetStatsPath {
server_id: String,
}
async fn stats(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Extension(periphery): PeripheryExtension,
Path(GetStatsPath { server_id }): Path<GetStatsPath>,
) -> anyhow::Result<Json<SystemStats>> {
let server = db
.servers
.find_one_by_id(&server_id)
.await
.context("failed at query to get server")?
.ok_or(anyhow!("failed to find server with id {server_id}"))?;
let permissions = get_user_permissions(&user.id, &server.permissions);
if permissions == PermissionLevel::None {
return Err(anyhow!("user does not have permissions on this server"));
}
let stats = periphery
.get_system_stats(&server)
.await
.context(format!("failed to get stats from server {}", server.name))?;
Ok(Json(stats))
}