Improve api schema

This commit is contained in:
Tobias Reisinger 2024-05-04 18:34:26 +02:00
parent f23bb48fa1
commit f9ad8f9399
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
9 changed files with 123 additions and 164 deletions

12
Cargo.lock generated
View file

@ -345,9 +345,9 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
@ -1363,9 +1363,9 @@ dependencies = [
[[package]] [[package]]
name = "num-iter" name = "num-iter"
version = "0.1.44" version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -1374,9 +1374,9 @@ dependencies = [
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm", "libm",

View file

@ -6,17 +6,9 @@
"url": "https://git.serguzim.me/emgauwa/" "url": "https://git.serguzim.me/emgauwa/"
}, },
"title": "Emgauwa API v1", "title": "Emgauwa API v1",
"version": "0.5.0", "version": "0.5.1",
"description": "Server API to manage an Emgauwa system." "description": "Server API to manage an Emgauwa system."
}, },
"servers": [
{
"url": "http://localhost:4419"
},
{
"url": "https://testing.emgauwa.app/"
}
],
"tags": [ "tags": [
{ {
"name": "schedules" "name": "schedules"
@ -123,17 +115,6 @@
} }
} }
} }
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "get-schedules-schedule_id", "operationId": "get-schedules-schedule_id",
@ -154,28 +135,6 @@
} }
} }
} }
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "put-schedules-schedule_id", "operationId": "put-schedules-schedule_id",
@ -216,13 +175,24 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/message"
}
}
}
}, },
"403": { "403": {
"description": "Forbidden" "description": "Forbidden",
}, "content": {
"404": { "application/json": {
"description": "Not Found" "schema": {
"$ref": "#/components/schemas/error"
}
}
}
} }
}, },
"operationId": "delete-schedules-schedule_id", "operationId": "delete-schedules-schedule_id",
@ -377,17 +347,6 @@
} }
} }
} }
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "get-controllers-controller_id", "operationId": "get-controllers-controller_id",
@ -408,28 +367,6 @@
} }
} }
} }
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "put-controllers-controller_id", "operationId": "put-controllers-controller_id",
@ -460,10 +397,14 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
}, "content": {
"404": { "application/json": {
"description": "Not Found" "schema": {
"$ref": "#/components/schemas/message"
}
}
}
} }
}, },
"operationId": "delete-controllers-controller_id", "operationId": "delete-controllers-controller_id",
@ -501,17 +442,6 @@
} }
} }
} }
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {}
}
}
}
} }
}, },
"operationId": "get-controllers-controller_id-relays", "operationId": "get-controllers-controller_id-relays",
@ -553,21 +483,10 @@
} }
} }
} }
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "get-controllers-controller_id-relays-relay_num", "operationId": "get-controllers-controller_id-relays-relay_num",
"description": "Return a single relay by number for a controller by id. When the relay or controller is not found, 404 will be returned." "description": "Return a single relay by number for a controller by id. When either the relay or the controller is not found, 404 will be returned."
}, },
"put": { "put": {
"summary": "overwrite single relay for single controller", "summary": "overwrite single relay for single controller",
@ -585,28 +504,6 @@
} }
} }
} }
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {}
}
}
}
} }
}, },
"operationId": "put-controllers-controller_id-relays-relay_num", "operationId": "put-controllers-controller_id-relays-relay_num",
@ -744,9 +641,6 @@
} }
} }
} }
},
"404": {
"description": "Not Found"
} }
}, },
"operationId": "get-tags-tag", "operationId": "get-tags-tag",
@ -757,10 +651,14 @@
"operationId": "delete-tags-tag", "operationId": "delete-tags-tag",
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
}, "content": {
"404": { "application/json": {
"description": "Not Found" "schema": {
"$ref": "#/components/schemas/message"
}
}
}
} }
}, },
"description": "delete tag from database and from affected relays and schedules", "description": "delete tag from database and from affected relays and schedules",
@ -792,10 +690,14 @@
"summary": "pulse relay on", "summary": "pulse relay on",
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
}, "content": {
"404": { "application/json": {
"description": "Not Found" "schema": {
"$ref": "#/components/schemas/message"
}
}
}
} }
}, },
"operationId": "post-controllers-controller_id-relays-relay_num-pulse", "operationId": "post-controllers-controller_id-relays-relay_num-pulse",
@ -960,7 +862,7 @@
} }
}, },
"operationId": "get-api-v1-macros-macro_id", "operationId": "get-api-v1-macros-macro_id",
"description": "Return a single macro by id. When no macro with the id is found 404 will be returned." "description": "Return a single macro by id."
}, },
"put": { "put": {
"summary": "overwrite a macro", "summary": "overwrite a macro",
@ -1035,7 +937,14 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/message"
}
}
}
} }
}, },
"operationId": "delete-api-v1-macros-macro_id", "operationId": "delete-api-v1-macros-macro_id",
@ -1067,10 +976,14 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
}, "content": {
"404": { "application/json": {
"description": "Not Found" "schema": {
"$ref": "#/components/schemas/message"
}
}
}
} }
}, },
"operationId": "put-api-v1-macros-macro_id-execute", "operationId": "put-api-v1-macros-macro_id-execute",
@ -1085,7 +998,17 @@
], ],
"responses": { "responses": {
"200": { "200": {
"description": "OK" "description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/schedule"
}
}
}
}
} }
}, },
"operationId": "post-schedules-list", "operationId": "post-schedules-list",
@ -1108,6 +1031,30 @@
}, },
"components": { "components": {
"schemas": { "schemas": {
"message": {
"title": "message",
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "action got handled"
}
}
},
"error": {
"title": "error",
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "bad input data"
},
"code": {
"type": "integer",
"example": 500
}
}
},
"controller": { "controller": {
"title": "controller", "title": "controller",
"type": "object", "type": "object",

View file

@ -1,6 +1,7 @@
use actix_web::{error, Error, HttpRequest, HttpResponse}; use actix_web::{error, Error, HttpRequest, HttpResponse, HttpResponseBuilder};
use serde::ser::SerializeStruct; use serde::ser::SerializeStruct;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use serde_json::json;
pub mod v1; pub mod v1;
@ -35,3 +36,12 @@ pub fn json_error_handler(err: error::JsonPayloadError, _: &HttpRequest) -> Erro
) )
.into() .into()
} }
pub trait EmgauwaMessage {
fn emgauwa_message(self, message: &str) -> HttpResponse;
}
impl EmgauwaMessage for HttpResponseBuilder {
fn emgauwa_message(mut self, message: &str) -> HttpResponse {
self.json(json!({ "message": message }))
}
}

View file

@ -8,6 +8,7 @@ use sqlx::{Pool, Sqlite};
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
use crate::handlers::EmgauwaMessage;
#[get("/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> {
@ -88,5 +89,5 @@ pub async fn delete(
.await??; .await??;
DbController::delete_by_uid(&mut pool_conn, uid).await?; DbController::delete_by_uid(&mut pool_conn, uid).await?;
Ok(HttpResponse::Ok().json("controller got deleted")) Ok(HttpResponse::Ok().emgauwa_message("controller got deleted"))
} }

View file

@ -12,6 +12,7 @@ use emgauwa_common::types::{
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
use crate::handlers::EmgauwaMessage;
#[get("/macros")] #[get("/macros")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> { pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, EmgauwaError> {
@ -98,7 +99,7 @@ pub async fn delete(
let uid = EmgauwaUid::try_from(macro_uid.as_str())?; let uid = EmgauwaUid::try_from(macro_uid.as_str())?;
DbMacro::delete_by_uid(&mut pool_conn, uid).await?; DbMacro::delete_by_uid(&mut pool_conn, uid).await?;
Ok(HttpResponse::Ok().json("macro got deleted")) Ok(HttpResponse::Ok().emgauwa_message("macro got deleted"))
} }
#[put("/macros/{macro_id}/execute")] #[put("/macros/{macro_id}/execute")]
@ -160,5 +161,5 @@ pub async fn execute(
.await??; .await??;
} }
Ok(HttpResponse::Ok().finish()) // TODO add a message? Ok(HttpResponse::Ok().emgauwa_message("macro got executed"))
} }

View file

@ -11,6 +11,7 @@ use sqlx::{Pool, Sqlite};
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
use crate::handlers::EmgauwaMessage;
#[get("/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> {
@ -181,5 +182,5 @@ pub async fn pulse(
}) })
.await??; .await??;
Ok(HttpResponse::Ok().finish()) // TODO add a message? Ok(HttpResponse::Ok().emgauwa_message("pulse sent"))
} }

View file

@ -12,6 +12,7 @@ use sqlx::{Pool, Sqlite};
use crate::app_state; use crate::app_state;
use crate::app_state::AppState; use crate::app_state::AppState;
use crate::handlers::EmgauwaMessage;
#[get("/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> {
@ -190,7 +191,7 @@ pub async fn delete(
ScheduleUid::On => Err(EmgauwaError::from(ApiError::ProtectedSchedule)), ScheduleUid::On => Err(EmgauwaError::from(ApiError::ProtectedSchedule)),
ScheduleUid::Any(_) => { ScheduleUid::Any(_) => {
DbSchedule::delete_by_uid(&mut pool_conn, uid).await?; DbSchedule::delete_by_uid(&mut pool_conn, uid).await?;
Ok(HttpResponse::Ok().json("schedule got deleted")) Ok(HttpResponse::Ok().emgauwa_message("schedule got deleted"))
} }
} }
} }

View file

@ -4,6 +4,7 @@ use emgauwa_common::errors::{DatabaseError, EmgauwaError};
use emgauwa_common::models::{FromDbModel, Tag}; use emgauwa_common::models::{FromDbModel, Tag};
use emgauwa_common::types::RequestTagCreate; use emgauwa_common::types::RequestTagCreate;
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
use crate::handlers::EmgauwaMessage;
#[get("/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> {
@ -43,7 +44,7 @@ pub async fn delete(
let (tag_name,) = path.into_inner(); let (tag_name,) = path.into_inner();
DbTag::delete_by_tag(&mut pool_conn, &tag_name).await?; DbTag::delete_by_tag(&mut pool_conn, &tag_name).await?;
Ok(HttpResponse::Ok().json("tag got deleted")) Ok(HttpResponse::Ok().emgauwa_message("tag got deleted"))
} }
#[post("/tags")] #[post("/tags")]

View file

@ -71,11 +71,8 @@ async fn main() -> Result<(), std::io::Error> {
} }
}); });
let mut api_v1_json = let api_v1_json =
serde_json::from_str(include_str!("../api.v1.json")).unwrap_or(api_default.clone()); serde_json::from_str(include_str!("../api.v1.json")).unwrap_or(api_default.clone());
api_v1_json["servers"] = json!([{
"url": "/",
}]);
App::new() App::new()