diff options
| -rw-r--r-- | src/cli.rs | 26 | ||||
| -rw-r--r-- | src/login/password.rs | 8 |
2 files changed, 29 insertions, 5 deletions
@@ -3,10 +3,15 @@ //! This module supports running `hi` as a freestanding program, via the //! [`Args`] struct. -use std::io; - -use axum::{middleware, Router}; -use clap::Parser; +use std::{future, io}; + +use axum::{ + http::header, + middleware, + response::{IntoResponse, Response}, + Router, +}; +use clap::{CommandFactory, Parser}; use sqlx::sqlite::SqlitePool; use tokio::net; @@ -32,6 +37,7 @@ use crate::{app::App, boot, channel, clock, db, event, expire, login, message, u /// ``` #[derive(Parser)] #[command( + version, about = "Run the `hi` server.", long_about = r#"Run the `hi` server. @@ -81,6 +87,7 @@ impl Args { expire::middleware, )) .route_layer(middleware::from_fn(clock::middleware)) + .route_layer(middleware::map_response(Self::server_info())) .with_state(app); let listener = self.listener().await?; @@ -106,6 +113,17 @@ impl Args { async fn pool(&self) -> Result<SqlitePool, db::Error> { db::prepare(&self.database_url, &self.backup_database_url).await } + + fn server_info() -> impl Clone + Fn(Response) -> future::Ready<Response> { + let command = Self::command(); + let name = command.get_name(); + let version = command.get_version().unwrap_or("unknown version"); + let version = format!("{name}/{version}"); + move |resp| { + let response = ([(header::SERVER, &version)], resp).into_response(); + future::ready(response) + } + } } fn routers() -> Router<App> { diff --git a/src/login/password.rs b/src/login/password.rs index da3930f..14fd981 100644 --- a/src/login/password.rs +++ b/src/login/password.rs @@ -4,7 +4,7 @@ use argon2::Argon2; use password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString}; use rand_core::OsRng; -#[derive(Debug, sqlx::Type)] +#[derive(sqlx::Type)] #[sqlx(transparent)] pub struct StoredHash(String); @@ -23,6 +23,12 @@ impl StoredHash { } } +impl fmt::Debug for StoredHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("StoredHash").field(&"********").finish() + } +} + #[derive(serde::Deserialize)] #[serde(transparent)] pub struct Password(String); |
