100 lines
3.9 KiB
Rust
100 lines
3.9 KiB
Rust
use std::sync::Arc;
|
|
|
|
use axum::{extract::State, http::HeaderMap, routing::get};
|
|
use reqwest::{header::USER_AGENT};
|
|
use sea_orm::{ConnectionTrait, Database, DatabaseConnection, EntityTrait, PaginatorTrait, Schema};
|
|
use utoipa::openapi::{ContactBuilder, InfoBuilder, LicenseBuilder};
|
|
use utoipa_axum::router::OpenApiRouter;
|
|
use utoipa_redoc::{Redoc, Servable};
|
|
use utoipa_swagger_ui::{Config, SwaggerUi};
|
|
use utoipa_axum::routes;
|
|
|
|
use crate::entities::prelude::BookInstance;
|
|
|
|
pub mod entities;
|
|
pub mod utils;
|
|
pub mod routes;
|
|
|
|
pub struct AppState {
|
|
app_name: String,
|
|
db_conn: Arc<DatabaseConnection>,
|
|
web_client: reqwest::Client
|
|
}
|
|
|
|
async fn index(
|
|
State(state): State<Arc<AppState>>
|
|
) ->String {
|
|
let app_name = &state.app_name;
|
|
let db_conn = &state.db_conn;
|
|
let status: &str = match db_conn.ping().await {
|
|
Ok(_) => "working",
|
|
Err(_) => "erroring"
|
|
};
|
|
let book_count = BookInstance::find().count(db_conn.as_ref()).await.unwrap();
|
|
format!("Hello from {app_name}! Database is {status}. We currently have {book_count} books in stock !")
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
let db: Arc<DatabaseConnection> = Arc::new(Database::connect(String::from("sqlite://./alexandria.db?mode=rwc")).await.unwrap());
|
|
|
|
let builder = db.get_database_backend();
|
|
let schema = Schema::new(builder);
|
|
if let Err(err) = db.execute(builder.build(schema.create_table_from_entity(crate::entities::prelude::Book).if_not_exists())).await {
|
|
println!("Error while creating book table: {err:?}");
|
|
return;
|
|
}
|
|
if let Err(err) = db.execute(builder.build(schema.create_table_from_entity(crate::entities::prelude::BookInstance).if_not_exists())).await {
|
|
println!("Error while creating book_instance table: {err:?}");
|
|
return;
|
|
}
|
|
if let Err(err) = db.execute(builder.build(schema.create_table_from_entity(crate::entities::prelude::Owner).if_not_exists())).await {
|
|
println!("Error while creating owner table: {err:?}");
|
|
return;
|
|
}
|
|
|
|
let mut default_headers = HeaderMap::new();
|
|
default_headers.append(USER_AGENT, "Alexandria/1.0 (unionetudianteauvergne@gmail.com)".parse().unwrap());
|
|
let shared_state = Arc::new(AppState {
|
|
app_name: "Alexandria".to_string(),
|
|
db_conn: db,
|
|
web_client: reqwest::Client::builder().default_headers(default_headers).build().expect("creating the reqwest client failed")
|
|
});
|
|
|
|
let (router, mut api) = OpenApiRouter::new()
|
|
.routes(routes!(routes::book::get_book_by_ean))
|
|
.routes(routes!(routes::book::get_book_by_id))
|
|
.routes(routes!(routes::book_instance::get_book_instance_by_id))
|
|
.routes(routes!(routes::book_instance::create_book_instance))
|
|
.routes(routes!(routes::owner::get_owner_by_id))
|
|
.routes(routes!(routes::owner::create_owner))
|
|
.route("/", get(index))
|
|
.with_state(shared_state)
|
|
.split_for_parts();
|
|
|
|
api.info = InfoBuilder::new()
|
|
.title("Alexandria")
|
|
.description(Some("Alexandria is a server that manages books and users for Union Étudiante's book exchange"))
|
|
.contact(Some(ContactBuilder::new()
|
|
.url(Some("https://ueauvergne.fr"))
|
|
.name(Some("Union Étudiante Auvergne"))
|
|
.email(Some("unionetudianteauvergne@gmail.com"))
|
|
.build()))
|
|
.license(Some(LicenseBuilder::new().name("MIT").url(Some("https://spdx.org/licenses/MIT.html")).build()))
|
|
.version("1.0.0")
|
|
.build();
|
|
|
|
let redoc = Redoc::with_url("/docs/", api.clone());
|
|
let swagger = SwaggerUi::new("/docs2/")
|
|
.url("/docs2/openapi.json", api)
|
|
.config(Config::default()
|
|
.try_it_out_enabled(true)
|
|
);
|
|
|
|
let router = router.merge(redoc);
|
|
let router = router.merge(swagger);
|
|
|
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
|
axum::serve(listener, router).await.unwrap();
|
|
}
|
|
|