This makes integration testing much easier as it can reuse the app instance.
This commit is contained in:
parent
79c4ab6c2b
commit
b22588cd0d
76
src/lib.rs
76
src/lib.rs
|
@ -11,3 +11,79 @@ pub mod middleware;
|
|||
mod test_utils;
|
||||
|
||||
pub use config::Config;
|
||||
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
use actix_web::middleware::ErrorHandlers;
|
||||
use actix_web::{cookie::Key, http::StatusCode, web, App, HttpResponse};
|
||||
use base64::prelude::{Engine as _, BASE64_STANDARD};
|
||||
use log::warn;
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::Embed;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::database::{
|
||||
ItemClassRepository, ItemEventRepository, ItemRepository, ItemStateRepository,
|
||||
};
|
||||
|
||||
#[derive(Embed)]
|
||||
#[folder = "static"]
|
||||
struct Static;
|
||||
|
||||
pub fn app(
|
||||
config: &Config,
|
||||
pool: &PgPool,
|
||||
) -> App<
|
||||
impl actix_web::dev::ServiceFactory<
|
||||
actix_web::dev::ServiceRequest,
|
||||
Config = (),
|
||||
Response = actix_web::dev::ServiceResponse<
|
||||
actix_web::body::EitherBody<actix_web::body::BoxBody>,
|
||||
>,
|
||||
Error = actix_web::Error,
|
||||
InitError = (),
|
||||
>,
|
||||
> {
|
||||
let secret_key = match config.secret_key {
|
||||
Some(ref encoded) => Key::from(
|
||||
&BASE64_STANDARD
|
||||
.decode(encoded)
|
||||
.expect("failed to decode base64 in SECRET_KEY"),
|
||||
),
|
||||
None => {
|
||||
warn!("SECRET_KEY was not specified, using randomly generated key");
|
||||
Key::generate()
|
||||
}
|
||||
};
|
||||
|
||||
App::new()
|
||||
.app_data(web::Data::new(config.clone()))
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.app_data(web::Data::new(ItemClassRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemEventRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemStateRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemRepository::new(pool.clone())))
|
||||
.service(web::scope("/static").route(
|
||||
"/{_:.*}",
|
||||
web::get().to(|path: web::Path<String>| async {
|
||||
Static::get(&path)
|
||||
.map(|embedded_file| match from_path(path.into_inner()).first() {
|
||||
Some(mime_type) => HttpResponse::Ok()
|
||||
.content_type(mime_type)
|
||||
.body(embedded_file.data),
|
||||
None => HttpResponse::Ok().body(embedded_file.data),
|
||||
})
|
||||
.unwrap_or(HttpResponse::NotFound().body(()))
|
||||
}),
|
||||
))
|
||||
.configure(frontend::config)
|
||||
.wrap(ErrorHandlers::new().handler(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
middleware::error_handlers::redirect_to_login,
|
||||
))
|
||||
.wrap(IdentityMiddleware::default())
|
||||
.wrap(SessionMiddleware::new(
|
||||
CookieSessionStore::default(),
|
||||
secret_key.clone(),
|
||||
))
|
||||
}
|
||||
|
|
72
src/main.rs
72
src/main.rs
|
@ -2,45 +2,20 @@
|
|||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
use actix_web::middleware::ErrorHandlers;
|
||||
use actix_web::{cookie::Key, http::StatusCode, web, App, HttpResponse, HttpServer};
|
||||
use base64::prelude::{Engine as _, BASE64_STANDARD};
|
||||
use actix_web::HttpServer;
|
||||
use clap::Parser;
|
||||
use li7y::database::item_events::ItemEventRepository;
|
||||
use li7y::database::item_states::ItemStateRepository;
|
||||
use li7y::database::items::ItemRepository;
|
||||
use li7y::database::ItemClassRepository;
|
||||
use log::{info, warn};
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::Embed;
|
||||
use log::info;
|
||||
|
||||
use li7y::Config;
|
||||
|
||||
#[derive(Embed)]
|
||||
#[folder = "static"]
|
||||
struct Static;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
|
||||
let config = Config::parse();
|
||||
|
||||
let secret_key = match config.secret_key {
|
||||
Some(ref encoded) => Key::from(
|
||||
&BASE64_STANDARD
|
||||
.decode(encoded)
|
||||
.expect("failed to decode base64 in SECRET_KEY"),
|
||||
),
|
||||
None => {
|
||||
warn!("SECRET_KEY was not specified, using randomly generated key");
|
||||
Key::generate()
|
||||
}
|
||||
};
|
||||
|
||||
let pool: sqlx::PgPool = sqlx::Pool::<sqlx::postgres::Postgres>::connect(&config.database_url)
|
||||
// This can’t be included in app, because app gets called in a (non-async) closure
|
||||
let pool = sqlx::Pool::<sqlx::postgres::Postgres>::connect(&config.database_url)
|
||||
.await
|
||||
.expect("failed to connect to database");
|
||||
|
||||
|
@ -54,39 +29,8 @@ async fn main() -> std::io::Result<()> {
|
|||
|
||||
info!("Starting on {address}:{port}");
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(config.clone()))
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.app_data(web::Data::new(ItemClassRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemEventRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemStateRepository::new(pool.clone())))
|
||||
.app_data(web::Data::new(ItemRepository::new(pool.clone())))
|
||||
.service(web::scope("/static").route(
|
||||
"/{_:.*}",
|
||||
web::get().to(|path: web::Path<String>| async {
|
||||
Static::get(&path)
|
||||
.map(|embedded_file| match from_path(path.into_inner()).first() {
|
||||
Some(mime_type) => HttpResponse::Ok()
|
||||
.content_type(mime_type)
|
||||
.body(embedded_file.data),
|
||||
None => HttpResponse::Ok().body(embedded_file.data),
|
||||
})
|
||||
.unwrap_or(HttpResponse::NotFound().body(()))
|
||||
}),
|
||||
))
|
||||
.configure(li7y::frontend::config)
|
||||
.wrap(ErrorHandlers::new().handler(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
li7y::middleware::error_handlers::redirect_to_login,
|
||||
))
|
||||
.wrap(IdentityMiddleware::default())
|
||||
.wrap(SessionMiddleware::new(
|
||||
CookieSessionStore::default(),
|
||||
secret_key.clone(),
|
||||
))
|
||||
})
|
||||
.bind((address, port))?
|
||||
.run()
|
||||
.await
|
||||
HttpServer::new(move || li7y::app(&config, &pool))
|
||||
.bind((address, port))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue