Use clap for configuration
This commit is contained in:
parent
bcbb7dfc67
commit
1e5f7930ab
55
Cargo.lock
generated
55
Cargo.lock
generated
|
@ -540,6 +540,46 @@ dependencies = [
|
|||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f6b81fb3c84f5563d509c59b5a48d935f689e993afa90fe39047f05adef9142"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca6706fd5224857d9ac5eb9355f6683563cc0541c7cd9d014043b57cbec78ac"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
|
@ -1016,6 +1056,12 @@ dependencies = [
|
|||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
|
@ -1170,6 +1216,7 @@ dependencies = [
|
|||
"actix-web",
|
||||
"barcoders",
|
||||
"base64 0.22.1",
|
||||
"clap",
|
||||
"datamatrix",
|
||||
"enum-iterator",
|
||||
"env_logger",
|
||||
|
@ -2042,7 +2089,7 @@ checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
|
|||
dependencies = [
|
||||
"dotenvy",
|
||||
"either",
|
||||
"heck",
|
||||
"heck 0.4.1",
|
||||
"hex",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
|
@ -2180,6 +2227,12 @@ dependencies = [
|
|||
"unicode-properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
|
|
|
@ -15,6 +15,7 @@ actix-session = { version = "0.9.0", features = ["cookie-session"] }
|
|||
actix-web = { version = "4.8.0", features = ["cookies"] }
|
||||
barcoders = { version = "2.0.0", default-features = false, features = ["std"] }
|
||||
base64 = "0.22.1"
|
||||
clap = { version = "4.5.10", features = ["derive", "env"] }
|
||||
datamatrix = "0.3.1"
|
||||
enum-iterator = "2.1.0"
|
||||
env_logger = "0.11.3"
|
||||
|
|
34
src/config.rs
Normal file
34
src/config.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
// SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use std::net::{IpAddr, Ipv6Addr};
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
/// A lightweight inventory management system
|
||||
#[derive(Clone, Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
pub struct Config {
|
||||
/// Database URL of PostgreSQL database
|
||||
#[arg(long, env)]
|
||||
pub database_url: String,
|
||||
|
||||
/// Secret key for encrypting session cookie
|
||||
///
|
||||
/// Can be generated with head -c 64 /dev/urandom | base64 -w0
|
||||
#[arg(long, env)]
|
||||
pub secret_key: Option<String>,
|
||||
|
||||
/// Address for HTTP server to listen on
|
||||
#[arg(long, env, default_value_t = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))]
|
||||
pub listen_address: std::net::IpAddr,
|
||||
|
||||
/// Port for HTTP server to listen on
|
||||
#[arg(long, env, default_value_t = 8080)]
|
||||
pub listen_port: u16,
|
||||
|
||||
/// Superuser password
|
||||
#[arg(long, env)]
|
||||
pub superuser_password: String,
|
||||
}
|
|
@ -59,12 +59,10 @@ async fn login(
|
|||
req: HttpRequest,
|
||||
form: web::Form<LoginForm>,
|
||||
query: web::Query<LoginQuery>,
|
||||
config: web::Data<crate::Config>,
|
||||
) -> Result<impl Responder, error::Error> {
|
||||
// Very basic authentication for now (only password, hardcoded in environment variable)
|
||||
if form.password
|
||||
== std::env::var("SUPERUSER_PASSWORD")
|
||||
.map_err(|_| error::ErrorInternalServerError("login disabled (no password set)"))?
|
||||
{
|
||||
// Very basic authentication for now (only password, hardcoded in configuration)
|
||||
if form.password == config.superuser_password {
|
||||
Identity::login(&req.extensions(), "superuser".into())
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
Ok(
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
mod config;
|
||||
pub mod frontend;
|
||||
pub mod label;
|
||||
pub mod middleware;
|
||||
|
||||
pub use config::Config;
|
||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -2,17 +2,18 @@
|
|||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use std::env;
|
||||
|
||||
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 clap::Parser;
|
||||
use log::{info, warn};
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::Embed;
|
||||
|
||||
use li7y::Config;
|
||||
|
||||
#[derive(Embed)]
|
||||
#[folder = "static"]
|
||||
struct Static;
|
||||
|
@ -21,39 +22,37 @@ struct Static;
|
|||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
|
||||
// generate a secret key with head -c 64 /dev/urandom | base64 -w0
|
||||
let secret_key = match env::var("SECRET_KEY") {
|
||||
Ok(encoded) => Key::from(
|
||||
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"),
|
||||
),
|
||||
Err(_) => {
|
||||
None => {
|
||||
warn!("SECRET_KEY was not specified, using randomly generated key");
|
||||
Key::generate()
|
||||
}
|
||||
};
|
||||
|
||||
let pool: sqlx::PgPool = sqlx::Pool::<sqlx::postgres::Postgres>::connect(
|
||||
&env::var("DATABASE_URL").expect("DATABASE_URL must be set"),
|
||||
)
|
||||
.await
|
||||
.expect("failed to connect to database");
|
||||
let pool: sqlx::PgPool = sqlx::Pool::<sqlx::postgres::Postgres>::connect(&config.database_url)
|
||||
.await
|
||||
.expect("failed to connect to database");
|
||||
|
||||
sqlx::migrate!()
|
||||
.run(&pool)
|
||||
.await
|
||||
.expect("failed to run migrations");
|
||||
|
||||
let address = env::var("LISTEN_ADDRESS").unwrap_or("::1".to_string());
|
||||
let port = env::var("LISTEN_PORT").map_or(8080, |s| {
|
||||
s.parse::<u16>().expect("failed to parse LISTEN_PORT")
|
||||
});
|
||||
let address = config.listen_address;
|
||||
let port = config.listen_port;
|
||||
|
||||
info!("Starting on {address}:{port}");
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(config.clone()))
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.service(web::scope("/static").route(
|
||||
"/{_:.*}",
|
||||
|
|
Loading…
Reference in a new issue