Add swagger-ui

This commit is contained in:
Tobias Reisinger 2024-04-22 03:41:41 +02:00
parent 51c42d5202
commit e950a33e98
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
9 changed files with 81 additions and 44 deletions

BIN
Cargo.lock generated

Binary file not shown.

View file

@ -12,6 +12,9 @@ actix-web = "4.4"
actix-web-actors = "4.2" actix-web-actors = "4.2"
actix-cors = "0.7" actix-cors = "0.7"
utoipa = "4.2"
utoipa-swagger-ui = { version = "6.0", features = ["actix-web", "debug-embed"] }
log = "0.4" log = "0.4"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }

View file

@ -1,3 +1,17 @@
use std::process::{exit, Command};
fn main() { fn main() {
println!("cargo:rustc-env=DATABASE_URL=sqlite://emgauwa-core.sqlite") println!("cargo:rustc-env=DATABASE_URL=sqlite://emgauwa-core.sqlite");
println!("cargo:rerun-if-changed=../api.v1.yaml");
let output = Command::new("sh")
.arg("-c")
.arg("yq . < ../api.v1.yaml > $OUT_DIR/api.v1.json")
.output()
.expect("Failed to convert api documentation to json");
if !output.status.success() {
eprintln!("Error: {}", String::from_utf8_lossy(&output.stderr));
exit(1);
}
} }

View file

@ -9,7 +9,7 @@ use sqlx::{Pool, Sqlite};
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
#[get("/api/v1/controllers")] #[get("/controllers")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> {
let mut pool_conn = pool.acquire().await?; let mut pool_conn = pool.acquire().await?;
@ -20,7 +20,7 @@ pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, Emgauw
Ok(HttpResponse::Ok().json(controllers)) Ok(HttpResponse::Ok().json(controllers))
} }
#[get("/api/v1/controllers/{controller_id}")] #[get("/controllers/{controller_id}")]
pub async fn show( pub async fn show(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -38,7 +38,7 @@ pub async fn show(
Ok(HttpResponse::Ok().json(return_controller)) Ok(HttpResponse::Ok().json(return_controller))
} }
#[put("/api/v1/controllers/{controller_id}")] #[put("/controllers/{controller_id}")]
pub async fn update( pub async fn update(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
app_state: web::Data<Addr<AppState>>, app_state: web::Data<Addr<AppState>>,
@ -70,7 +70,7 @@ pub async fn update(
Ok(HttpResponse::Ok().json(return_controller)) Ok(HttpResponse::Ok().json(return_controller))
} }
#[delete("/api/v1/controllers/{controller_id}")] #[delete("/controllers/{controller_id}")]
pub async fn delete( pub async fn delete(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
app_state: web::Data<Addr<AppState>>, app_state: web::Data<Addr<AppState>>,

View file

@ -10,7 +10,7 @@ use sqlx::{Pool, Sqlite};
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
#[get("/api/v1/relays")] #[get("/relays")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> {
let mut pool_conn = pool.acquire().await?; let mut pool_conn = pool.acquire().await?;
@ -21,7 +21,7 @@ pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, Emgauw
Ok(HttpResponse::Ok().json(relays)) Ok(HttpResponse::Ok().json(relays))
} }
#[get("/api/v1/relays/tag/{tag}")] #[get("/relays/tag/{tag}")]
pub async fn tagged( pub async fn tagged(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -39,7 +39,7 @@ pub async fn tagged(
Ok(HttpResponse::Ok().json(relays)) Ok(HttpResponse::Ok().json(relays))
} }
#[get("/api/v1/controllers/{controller_id}/relays")] #[get("/controllers/{controller_id}/relays")]
pub async fn index_for_controller( pub async fn index_for_controller(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -59,7 +59,7 @@ pub async fn index_for_controller(
Ok(HttpResponse::Ok().json(relays)) Ok(HttpResponse::Ok().json(relays))
} }
#[get("/api/v1/controllers/{controller_id}/relays/{relay_num}")] #[get("/controllers/{controller_id}/relays/{relay_num}")]
pub async fn show_for_controller( pub async fn show_for_controller(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String, i64)>, path: web::Path<(String, i64)>,
@ -81,7 +81,7 @@ pub async fn show_for_controller(
Ok(HttpResponse::Ok().json(return_relay)) Ok(HttpResponse::Ok().json(return_relay))
} }
#[put("/api/v1/controllers/{controller_id}/relays/{relay_num}")] #[put("/controllers/{controller_id}/relays/{relay_num}")]
pub async fn update_for_controller( pub async fn update_for_controller(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
app_state: web::Data<Addr<AppState>>, app_state: web::Data<Addr<AppState>>,

View file

@ -6,7 +6,7 @@ use emgauwa_lib::types::{RequestCreateSchedule, RequestUpdateSchedule, ScheduleU
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
#[get("/api/v1/schedules")] #[get("/schedules")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> {
let mut pool_conn = pool.acquire().await?; let mut pool_conn = pool.acquire().await?;
@ -16,7 +16,7 @@ pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, Emgauw
Ok(HttpResponse::Ok().json(schedules)) Ok(HttpResponse::Ok().json(schedules))
} }
#[get("/api/v1/schedules/tag/{tag}")] #[get("/schedules/tag/{tag}")]
pub async fn tagged( pub async fn tagged(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -34,7 +34,7 @@ pub async fn tagged(
Ok(HttpResponse::Ok().json(schedules)) Ok(HttpResponse::Ok().json(schedules))
} }
#[get("/api/v1/schedules/{schedule_id}")] #[get("/schedules/{schedule_id}")]
pub async fn show( pub async fn show(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -52,7 +52,7 @@ pub async fn show(
Ok(HttpResponse::Ok().json(return_schedule)) Ok(HttpResponse::Ok().json(return_schedule))
} }
#[post("/api/v1/schedules")] #[post("/schedules")]
pub async fn add( pub async fn add(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
data: web::Json<RequestCreateSchedule>, data: web::Json<RequestCreateSchedule>,
@ -96,7 +96,7 @@ async fn add_list_single(
Ok(new_schedule) Ok(new_schedule)
} }
#[post("/api/v1/schedules/list")] #[post("/schedules/list")]
pub async fn add_list( pub async fn add_list(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
data: web::Json<Vec<RequestCreateSchedule>>, data: web::Json<Vec<RequestCreateSchedule>>,
@ -113,7 +113,7 @@ pub async fn add_list(
Ok(HttpResponse::Created().json(schedules)) Ok(HttpResponse::Created().json(schedules))
} }
#[put("/api/v1/schedules/{schedule_id}")] #[put("/schedules/{schedule_id}")]
pub async fn update( pub async fn update(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -148,7 +148,7 @@ pub async fn update(
Ok(HttpResponse::Ok().json(return_schedule)) Ok(HttpResponse::Ok().json(return_schedule))
} }
#[delete("/api/v1/schedules/{schedule_id}")] #[delete("/schedules/{schedule_id}")]
pub async fn delete( pub async fn delete(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,

View file

@ -5,7 +5,7 @@ use emgauwa_lib::models::{FromDbModel, Tag};
use emgauwa_lib::types::RequestCreateTag; use emgauwa_lib::types::RequestCreateTag;
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
#[get("/api/v1/tags")] #[get("/tags")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> {
let mut pool_conn = pool.acquire().await?; let mut pool_conn = pool.acquire().await?;
@ -16,7 +16,7 @@ pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, Emgauw
Ok(HttpResponse::Ok().json(tags)) Ok(HttpResponse::Ok().json(tags))
} }
#[get("/api/v1/tags/{tag_name}")] #[get("/tags/{tag_name}")]
pub async fn show( pub async fn show(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -33,7 +33,7 @@ pub async fn show(
Ok(HttpResponse::Ok().json(return_tag)) Ok(HttpResponse::Ok().json(return_tag))
} }
#[delete("/api/v1/tags/{tag_name}")] #[delete("/tags/{tag_name}")]
pub async fn delete( pub async fn delete(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
path: web::Path<(String,)>, path: web::Path<(String,)>,
@ -46,7 +46,7 @@ pub async fn delete(
Ok(HttpResponse::Ok().json("tag got deleted")) Ok(HttpResponse::Ok().json("tag got deleted"))
} }
#[post("/api/v1/tags")] #[post("/tags")]
pub async fn add( pub async fn add(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
data: web::Json<RequestCreateTag>, data: web::Json<RequestCreateTag>,

View file

@ -11,7 +11,7 @@ use crate::handlers::v1::ws::controllers::ControllerWs;
pub mod controllers; pub mod controllers;
#[get("/api/v1/ws/controllers")] #[get("/ws/controllers")]
pub async fn ws_controllers( pub async fn ws_controllers(
pool: web::Data<Pool<Sqlite>>, pool: web::Data<Pool<Sqlite>>,
app_state: web::Data<Addr<AppState>>, app_state: web::Data<Addr<AppState>>,

View file

@ -7,6 +7,8 @@ use actix_web::{middleware, web, App, HttpServer};
use emgauwa_lib::db::DbController; use emgauwa_lib::db::DbController;
use emgauwa_lib::errors::EmgauwaError; use emgauwa_lib::errors::EmgauwaError;
use emgauwa_lib::utils::{drop_privileges, init_logging}; use emgauwa_lib::utils::{drop_privileges, init_logging};
use serde_json::json;
use utoipa_swagger_ui::SwaggerUi;
use crate::app_state::AppState; use crate::app_state::AppState;
@ -61,13 +63,30 @@ async fn main() -> Result<(), std::io::Error> {
}), }),
}; };
let api_default = json!({
"openapi": "3.0.0",
"info": {
"version": "0.0.0",
"title": "Failed to load API documentation",
}
});
let api_v1_json =
serde_json::from_str(include_str!(concat!(env!("OUT_DIR"), "/api.v1.json")))
.unwrap_or(api_default.clone());
App::new() App::new()
.wrap(cors) .wrap(cors)
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
.wrap(middleware::NormalizePath::new(TrailingSlash::Trim))
.app_data(web::JsonConfig::default().error_handler(handlers::json_error_handler)) .app_data(web::JsonConfig::default().error_handler(handlers::json_error_handler))
.app_data(web::Data::new(pool.clone())) .app_data(web::Data::new(pool.clone()))
.app_data(web::Data::new(app_state.clone())) .app_data(web::Data::new(app_state.clone()))
.service(
SwaggerUi::new("/api/docs/{_:.*}")
.external_urls_from_iter_unchecked([("/api/v1.json", api_v1_json)]),
)
.service(
web::scope("/api/v1")
.wrap(middleware::NormalizePath::new(TrailingSlash::Trim))
.service(handlers::v1::controllers::index) .service(handlers::v1::controllers::index)
.service(handlers::v1::controllers::show) .service(handlers::v1::controllers::show)
.service(handlers::v1::controllers::update) .service(handlers::v1::controllers::update)
@ -88,7 +107,8 @@ async fn main() -> Result<(), std::io::Error> {
.service(handlers::v1::tags::show) .service(handlers::v1::tags::show)
.service(handlers::v1::tags::delete) .service(handlers::v1::tags::delete)
.service(handlers::v1::tags::add) .service(handlers::v1::tags::add)
.service(handlers::v1::ws::ws_controllers) .service(handlers::v1::ws::ws_controllers),
)
}) })
.listen(listener)? .listen(listener)?
.run() .run()