// trifid-api, an open source reimplementation of the Defined Networking nebula management server. // Copyright (C) 2023 c0repwn3r // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use std::error::Error; use std::time::Duration; use actix_request_identifier::RequestIdentifier; use actix_web::{App, HttpResponse, HttpServer, web::{Data, JsonConfig}}; use log::{info, Level}; use sea_orm::{ConnectOptions, Database, DatabaseConnection}; use trifid_api_migration::{Migrator, MigratorTrait}; use crate::config::CONFIG; use crate::error::{APIError, APIErrorsResponse}; use crate::tokens::random_id_no_id; pub mod config; pub mod routes; pub mod error; pub mod tokens; pub mod timers; pub mod magic_link; pub mod auth_tokens; pub mod cursor; pub mod crypto; pub struct AppState { pub conn: DatabaseConnection } #[actix_web::main] async fn main() -> Result<(), Box> { simple_logger::init_with_level(Level::Debug).unwrap(); info!("Connecting to database at {}...", CONFIG.database.url); let mut opt = ConnectOptions::new(CONFIG.database.url.clone()); opt.max_connections(CONFIG.database.max_connections) .min_connections(CONFIG.database.min_connections) .connect_timeout(Duration::from_secs(CONFIG.database.connect_timeout)) .acquire_timeout(Duration::from_secs(CONFIG.database.acquire_timeout)) .idle_timeout(Duration::from_secs(CONFIG.database.idle_timeout)) .max_lifetime(Duration::from_secs(CONFIG.database.max_lifetime)) .sqlx_logging(CONFIG.database.sqlx_logging) .sqlx_logging_level(log::LevelFilter::Info); let db = Database::connect(opt).await?; info!("Performing database migration..."); Migrator::up(&db, None).await?; let data = Data::new(AppState { conn: db }); HttpServer::new(move || { App::new() .app_data(data.clone()) .app_data(JsonConfig::default().error_handler(|err, _req| { let api_error: APIError = (&err).into(); actix_web::error::InternalError::from_response( err, HttpResponse::BadRequest().json(APIErrorsResponse { errors: vec![ api_error ], }) ).into() })) .wrap(RequestIdentifier::with_generator(random_id_no_id)) .service(routes::v1::auth::magic_link::magic_link_request) .service(routes::v1::signup::signup_request) .service(routes::v1::auth::verify_magic_link::verify_magic_link_request) .service(routes::v1::totp_authenticators::totp_authenticators_request) .service(routes::v1::verify_totp_authenticators::verify_totp_authenticators_request) .service(routes::v1::auth::totp::totp_request) .service(routes::v1::networks::get_networks) .service(routes::v1::organization::create_org_request) .service(routes::v1::networks::get_network_request) .service(routes::v1::roles::create_role_request) .service(routes::v1::roles::get_roles) .service(routes::v1::roles::get_role) }).bind(CONFIG.server.bind)?.run().await?; Ok(()) }