trifid/trifid-api/src/main.rs

136 lines
4.0 KiB
Rust
Raw Normal View History

2023-11-19 03:51:45 +00:00
use std::fs;
use std::path::PathBuf;
use actix_web::{App, Error, HttpResponse, HttpServer};
use actix_web::middleware::Logger;
use actix_web::web::{Data, JsonConfig};
use diesel::Connection;
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
use diesel_async::AsyncPgConnection;
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
use diesel_async::pooled_connection::bb8::Pool;
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use log::{error, info};
use crate::config::Config;
use crate::error::APIErrorResponse;
2023-04-02 17:06:16 +00:00
pub mod error;
2023-11-19 15:49:08 +00:00
#[macro_use]
2023-08-19 03:55:27 +00:00
pub mod response;
2023-11-19 03:51:45 +00:00
pub mod config;
pub mod routes;
2023-11-19 15:49:08 +00:00
pub mod schema;
pub mod models;
#[macro_use]
pub mod id;
2023-11-19 16:31:30 +00:00
pub mod email;
2023-11-19 15:49:08 +00:00
2023-04-02 19:25:52 +00:00
2023-11-19 03:51:45 +00:00
#[derive(Clone)]
2023-04-02 19:25:52 +00:00
pub struct AppState {
2023-11-19 03:51:45 +00:00
pub config: Config,
pub pool: bb8::Pool<AsyncDieselConnectionManager<AsyncPgConnection>>
2023-04-02 19:25:52 +00:00
}
2023-02-20 18:42:15 +00:00
2023-11-19 03:51:45 +00:00
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
2023-04-02 16:08:36 +00:00
#[actix_web::main]
2023-11-19 03:51:45 +00:00
async fn main() {
env_logger::init();
info!("Trifid API v{} starting up", env!("CARGO_PKG_VERSION"));
let mut args = std::env::args();
let config_path = match args.nth(1) {
Some(path) => path,
None => {
eprintln!("usage: trifid-api <config_path>");
std::process::exit(1);
}
};
2023-02-03 02:39:41 +00:00
2023-11-19 03:51:45 +00:00
let config_pathbuf = PathBuf::from(config_path);
info!("Loading config from {}", config_pathbuf.display());
2023-02-03 02:39:41 +00:00
2023-11-19 03:51:45 +00:00
let config_str = match fs::read_to_string(&config_pathbuf) {
Ok(c_str) => c_str,
Err(e) => {
error!("Error loading configuration from {}: {}", config_pathbuf.display(), e);
std::process::exit(1);
}
};
2023-02-03 02:39:41 +00:00
2023-11-19 03:51:45 +00:00
let config: Config = match toml::from_str(&config_str) {
Ok(config) => config,
Err(e) => {
error!("Error parsing configuration in {}: {}", config_pathbuf.display(), e);
std::process::exit(1);
}
};
2023-02-03 02:39:41 +00:00
2023-11-19 03:51:45 +00:00
info!("Connecting to the database...");
2023-04-02 17:06:16 +00:00
2023-11-19 03:51:45 +00:00
let pool_config = AsyncDieselConnectionManager::<AsyncPgConnection>::new(&config.database.url);
let pool = match Pool::builder().build(pool_config).await {
Ok(pool) => pool,
Err(e) => {
error!("Error while creating database pool: {}", e);
std::process::exit(1);
}
};
2023-04-02 17:06:16 +00:00
2023-11-19 03:51:45 +00:00
info!("Running pending migrations...");
2023-11-19 15:49:08 +00:00
let local_config = config.clone();
let db_url = config.database.url.clone();
match actix_web::rt::task::spawn_blocking(move || { // Lock block
let mut conn = match AsyncConnectionWrapper::<AsyncPgConnection>::establish(&db_url) {
2023-11-19 03:51:45 +00:00
Ok(conn) => conn,
Err(e) => {
error!("Error acquiring connection from pool: {}", e);
std::process::exit(1);
}
};
match conn.run_pending_migrations(MIGRATIONS) {
Ok(_) => (),
Err(e) => {
2023-11-19 15:49:08 +00:00
error!("Failed to run pending migrations: {}", e);
std::process::exit(1);
2023-11-19 03:51:45 +00:00
}
}
2023-11-19 15:49:08 +00:00
}).await {
Ok(_) => (),
Err(e) => {
error!("Error waiting for migrations: {}", e);
std::process::exit(1);
}
2023-11-19 03:51:45 +00:00
}
let app_state = Data::new(AppState {
config,
pool
});
let server = HttpServer::new(move || {
2023-04-02 17:06:16 +00:00
App::new()
2023-11-19 03:51:45 +00:00
.app_data(JsonConfig::default().error_handler(|err, _rq| {
Error::from({
let err2: APIErrorResponse = (&err).into();
actix_web::error::InternalError::from_response(
err,
HttpResponse::BadRequest().json(err2),
)
})
}))
2023-11-19 15:49:08 +00:00
.service(routes::v1::signup::signup_req)
2023-11-20 01:58:46 +00:00
.service(routes::v1::auth::verify_magic_link::verify_link_req)
2023-11-19 03:51:45 +00:00
.wrap(Logger::default())
.wrap(actix_cors::Cors::permissive())
.app_data(app_state.clone())
}).bind((local_config.server.bind.ip, local_config.server.bind.port)).unwrap();
server.run().await.unwrap();
info!("Goodbye!");
2023-04-02 16:08:36 +00:00
}