feat: switched to clap for CLI
parent
7cf0e44b65
commit
3800534a51
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
db.sqlite
|
db.sqlite
|
||||||
|
data
|
||||||
|
|
|
@ -68,6 +68,55 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argon2"
|
name = "argon2"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -290,6 +339,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"clap",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"r2d2_sqlite",
|
"r2d2_sqlite",
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -354,6 +404,52 @@ dependencies = [
|
||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
|
@ -595,6 +691,12 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -730,6 +832,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
@ -836,7 +944,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1333,9 +1441,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@ -1457,7 +1571,7 @@ dependencies = [
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1671,6 +1785,12 @@ version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
@ -1791,7 +1911,7 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1818,6 +1938,15 @@ dependencies = [
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
|
@ -12,6 +12,7 @@ argon2 = "0.5.3"
|
||||||
axum = { version = "0.8.0", features = ["macros"] }
|
axum = { version = "0.8.0", features = ["macros"] }
|
||||||
axum-extra = { version = "0.10.0", features = ["cookie"] }
|
axum-extra = { version = "0.10.0", features = ["cookie"] }
|
||||||
chrono = { version = "0.4.39", features = ["serde"] }
|
chrono = { version = "0.4.39", features = ["serde"] }
|
||||||
|
clap = { version = "4.5.26", features = ["derive", "env"] }
|
||||||
r2d2 = "0.8.10"
|
r2d2 = "0.8.10"
|
||||||
r2d2_sqlite = "0.25.0"
|
r2d2_sqlite = "0.25.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
@ -24,3 +25,6 @@ tokio = { version = "1.42.0", features = ["full"] }
|
||||||
tower-http = { version = "0.6.2", features = ["compression-br", "compression-gzip", "set-header", "fs"] }
|
tower-http = { version = "0.6.2", features = ["compression-br", "compression-gzip", "set-header", "fs"] }
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = "0.3.19"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::{Args, Parser, Subcommand};
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
pub struct Cli {
|
||||||
|
#[arg(
|
||||||
|
long = "templates",
|
||||||
|
default_value = "./templates",
|
||||||
|
value_name = "TEMPLATES_DIR",
|
||||||
|
env = "TEMPLATES_DIR"
|
||||||
|
)]
|
||||||
|
pub templates_dir: PathBuf,
|
||||||
|
#[arg(
|
||||||
|
long = "static",
|
||||||
|
default_value = "./static",
|
||||||
|
value_name = "STATIC_DIR",
|
||||||
|
env = "STATIC_DIR"
|
||||||
|
)]
|
||||||
|
pub static_dir: PathBuf,
|
||||||
|
#[arg(
|
||||||
|
long = "data",
|
||||||
|
default_value = "./data",
|
||||||
|
value_name = "DATA_DIR",
|
||||||
|
env = "DATA_DIR"
|
||||||
|
)]
|
||||||
|
pub data_dir: PathBuf,
|
||||||
|
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub cmd: Subcommands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Subcommands {
|
||||||
|
Serve { domain: String, port: u16 },
|
||||||
|
User(UserCmd),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Args)]
|
||||||
|
pub struct UserCmd {
|
||||||
|
#[command(subcommand)]
|
||||||
|
cmd: UserSubCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum UserSubCmd {
|
||||||
|
List,
|
||||||
|
Remove {
|
||||||
|
username: String,
|
||||||
|
},
|
||||||
|
Add {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
#[arg(long, default_value_t = false)]
|
||||||
|
admin: bool,
|
||||||
|
},
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
use argon2::password_hash::rand_core::{OsRng, RngCore};
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rusqlite::Row;
|
use rusqlite::Row;
|
||||||
|
|
||||||
|
|
59
src/main.rs
59
src/main.rs
|
@ -1,8 +1,12 @@
|
||||||
|
mod cli;
|
||||||
mod db;
|
mod db;
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::{fs, path::Path, sync::Arc};
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use cli::UserCmd;
|
||||||
|
use db::DbError;
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
use tera::Tera;
|
use tera::Tera;
|
||||||
use tower_http::compression::CompressionLayer;
|
use tower_http::compression::CompressionLayer;
|
||||||
|
@ -14,6 +18,7 @@ const MIGRATIONS: [&str; 5] = [
|
||||||
include_str!("migrations/003_events.sql"),
|
include_str!("migrations/003_events.sql"),
|
||||||
include_str!("migrations/004_auth.sql"),
|
include_str!("migrations/004_auth.sql"),
|
||||||
];
|
];
|
||||||
|
const DB_FILENAME: &str = "db.sqlite3";
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
|
@ -21,31 +26,47 @@ pub struct Context {
|
||||||
tera: Arc<Tera>,
|
tera: Arc<Tera>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_user_cli(data_dir: impl AsRef<Path>, cmd: UserCmd) -> Result<(), DbError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
tracing_subscriber::fmt::init();
|
let args = cli::Cli::parse();
|
||||||
|
|
||||||
let manager = SqliteConnectionManager::file("db.sqlite");
|
match args.cmd {
|
||||||
let pool = r2d2::Pool::new(manager).unwrap();
|
cli::Subcommands::Serve { domain, port } => {
|
||||||
db::run_migrations(&pool, &MIGRATIONS).unwrap();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let template_dir = std::env::var("TEMPLATE_DIR").unwrap_or(String::from("./templates"));
|
if !fs::exists(&args.data_dir).unwrap() {
|
||||||
let tera = Tera::new(&format!("{template_dir}/**/*")).unwrap();
|
fs::create_dir_all(&args.data_dir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let static_dir = std::env::var("STATIC_DIR").unwrap_or(String::from("./static"));
|
let manager = SqliteConnectionManager::file(args.data_dir.join(DB_FILENAME));
|
||||||
|
let pool = r2d2::Pool::new(manager).unwrap();
|
||||||
|
db::run_migrations(&pool, &MIGRATIONS).unwrap();
|
||||||
|
|
||||||
let ctx = Context {
|
let tera =
|
||||||
pool,
|
Tera::new(&format!("{}/**/*", args.templates_dir.to_string_lossy())).unwrap();
|
||||||
tera: Arc::new(tera),
|
|
||||||
};
|
|
||||||
let app = server::app(ctx, &static_dir).layer(CompressionLayer::new().br(true).gzip(true));
|
|
||||||
|
|
||||||
let address = "0.0.0.0:8000";
|
let ctx = Context {
|
||||||
|
pool,
|
||||||
|
tera: Arc::new(tera),
|
||||||
|
};
|
||||||
|
let app = server::app(ctx, &args.static_dir)
|
||||||
|
.layer(CompressionLayer::new().br(true).gzip(true));
|
||||||
|
|
||||||
tracing::info!("Starting server on {address}");
|
let address = format!("{}:{}", domain, port);
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
tracing::info!("Starting server on {address}");
|
||||||
axum::serve(listener, app.into_make_service())
|
|
||||||
.await
|
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
||||||
.unwrap();
|
axum::serve(listener, app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
cli::Subcommands::User(cmd) => {
|
||||||
|
run_user_cli(&args.data_dir, cmd).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ mod error;
|
||||||
mod events;
|
mod events;
|
||||||
mod plants;
|
mod plants;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::State,
|
extract::State,
|
||||||
http::{header::VARY, HeaderMap, HeaderValue},
|
http::{header::VARY, HeaderMap, HeaderValue},
|
||||||
|
@ -50,7 +52,7 @@ pub fn render_view(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app(ctx: crate::Context, static_dir: &str) -> axum::Router {
|
pub fn app(ctx: crate::Context, static_dir: impl AsRef<Path>) -> axum::Router {
|
||||||
let router = Router::new()
|
let router = Router::new()
|
||||||
.nest("/plants", plants::app())
|
.nest("/plants", plants::app())
|
||||||
.nest("/comments", comments::app())
|
.nest("/comments", comments::app())
|
||||||
|
|
Loading…
Reference in New Issue