Feat: Implement basic web authentication and UI

This commit introduces the foundation for web-based authentication and
user interface. It includes:

- **Session Management**: Securely handling user sessions using
  cryptographically generated tokens, cookies with appropriate security
  flags, and server-side storage.
- **Login/Logout Functionality**: Endpoints for users to log in with
  their credentials and log out, clearing their session.
- **User Interface**: Basic templates for the login page, a list of
  cases, and a detailed view of a single case, allowing users to
  navigate and view their data.
- **Authorization**: An `AuthenticatedWebUser` extractor to ensure only
  logged-in users can access protected web routes.
- **Configuration**: Added a `cookie_secure` option to the configuration
  to control the `Secure` flag on session cookies, useful for local
  development.
- **Dependencies**: Added necessary dependencies for password hashing,
  time handling, and TOML file manipulation.
- **Helper Binary**: Included a `hash-password` binary to simplify
  generating bcrypt hashes for user passwords.
This commit is contained in:
2026-04-14 15:09:23 +02:00
parent 61b5c8e125
commit d489716c9b
24 changed files with 930 additions and 16 deletions
+10
View File
@@ -4,6 +4,7 @@ pub mod error;
pub mod models;
pub mod routes;
pub mod transcribe;
pub mod web_session;
use std::sync::Arc;
@@ -12,6 +13,7 @@ use axum::Router;
use config::Config;
use transcribe::TranscribeSender;
use web_session::SessionStore;
/// Shared application state. Clonable — all fields are cheap to clone
/// (`Arc` and `mpsc::Sender`).
@@ -19,6 +21,7 @@ use transcribe::TranscribeSender;
pub struct AppState {
pub config: Arc<Config>,
pub transcribe_tx: TranscribeSender,
pub session_store: SessionStore,
}
impl FromRef<AppState> for Arc<Config> {
@@ -33,6 +36,12 @@ impl FromRef<AppState> for TranscribeSender {
}
}
impl FromRef<AppState> for SessionStore {
fn from_ref(state: &AppState) -> Self {
state.session_store.clone()
}
}
/// Test/simple entrypoint: jobs pushed into the transcribe channel are dropped
/// because the receiver is not retained. Use [`create_router_with_state`] from
/// `main.rs` where a real worker owns the receiver.
@@ -41,6 +50,7 @@ pub fn create_router(config: Arc<Config>) -> Router {
create_router_with_state(AppState {
config,
transcribe_tx: tx,
session_store: web_session::new_store(),
})
}