auth #28

Merged
philipp merged 4 commits from auth into main 2025-04-12 19:49:47 +02:00
7 changed files with 122 additions and 20 deletions
Showing only changes of commit 004b9d1408 - Show all commits

90
Cargo.lock generated
View File

@ -1267,6 +1267,16 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
@ -1335,6 +1345,12 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking"
version = "2.2.1"
@ -1924,6 +1940,15 @@ dependencies = [
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -2213,6 +2238,7 @@ dependencies = [
"tower-sessions",
"tower-sessions-sqlx-store-chrono",
"tracing",
"tracing-subscriber",
]
[[package]]
@ -2293,6 +2319,16 @@ dependencies = [
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "time"
version = "0.3.41"
@ -2562,6 +2598,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
@ -2655,6 +2717,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -2784,6 +2852,22 @@ dependencies = [
"wasite",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.9"
@ -2793,6 +2877,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.61.0"

View File

@ -19,6 +19,7 @@ thiserror = "2.0"
async-trait = "0.1"
password-auth = "1.0"
tower-sessions-sqlx-store-chrono = { version = "0.14", features = ["sqlite"] }
tracing-subscriber = "0.3"
[dev-dependencies]

1
seeds.sql Normal file
View File

@ -0,0 +1 @@
insert into user(name, pw) values('a', '$argon2i$v=19$m=16,t=2,p=1$b2lmaG9pMzJvNDk$vXbHg45vkuMrQaP0XY184Q'); // pw = 123

View File

@ -11,6 +11,9 @@ pub(crate) mod team;
async fn index(session: Session) -> Markup {
let content = html! {
h1 { (t!("app_name")) }
a href="/auth/logout" {
"Ausloggen"
}
nav {
ul {
li {

View File

@ -19,14 +19,13 @@ pub type UserId<Backend> = <<Backend as AuthnBackend>::User as AuthUser>::Id;
pub struct User {
id: i64,
name: String,
password: String,
pw: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Credentials {
pub name: String,
pub password: String,
pub next: Option<String>,
}
impl AuthUser for User {
@ -37,7 +36,7 @@ impl AuthUser for User {
}
fn session_auth_hash(&self) -> &[u8] {
&self.password.as_bytes()
&self.pw.as_bytes()
}
}
@ -69,18 +68,18 @@ impl AuthnBackend for Backend {
creds: Self::Credentials,
) -> Result<Option<Self::User>, Self::Error> {
let user: Option<Self::User> =
sqlx::query_as("select id, name, pw from user where name = ? ")
sqlx::query_as("SELECT id, name, pw FROM user WHERE name = ? ")
.bind(creds.name)
.fetch_optional(&self.db)
.await?;
// We're using password-based authentication--this works by comparing our form
// input with an argon2 password hash.
Ok(user.filter(|user| verify_password(creds.password, &user.password).is_ok()))
Ok(user.filter(|user| verify_password(creds.password, &user.pw).is_ok()))
}
async fn get_user(&self, user_id: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {
let user = sqlx::query_as("select id, name, pw from user where id = ?")
let user = sqlx::query_as("SELECT id, name, pw FROM user WHERE id = ?")
.bind(user_id)
.fetch_optional(&self.db)
.await?;
@ -101,11 +100,22 @@ pub fn routes() -> Router<AppState> {
async fn login(session: Session) -> Markup {
let content = html! {
h1 { "Login" }
form action="/auth/login" method="post" {
label {
"Name"
input type="text" name="name";
}
label {
"Passwort"
input type="password" name="password";
}
input type="submit" value="Einloggen";
}
};
// TODO: generate okayish looking login page
page(content, session, false)
page(content, session, false).await
}
pub async fn login_post(
@ -118,12 +128,7 @@ pub async fn login_post(
Ok(None) => {
err!(session, "Invalid credentials");
let mut login_url = "/auth/login".to_string();
if let Some(next) = creds.next {
login_url = format!("{login_url}?next={next}");
};
return Redirect::to(&login_url).into_response();
return Redirect::to("/auth/login").into_response();
}
Err(_) => return StatusCode::INTERNAL_SERVER_ERROR.into_response(),
};
@ -134,12 +139,7 @@ pub async fn login_post(
succ!(session, "Successfully logged in as {}", user.name);
if let Some(ref next) = creds.next {
Redirect::to(next)
} else {
Redirect::to("/")
}
.into_response()
Redirect::to("/admin").into_response()
}
pub async fn logout(mut auth_session: AuthSession) -> impl IntoResponse {

View File

@ -1,11 +1,17 @@
use dotenv::dotenv;
use sqlx::{SqlitePool, pool::PoolOptions};
use sqlx::{pool::PoolOptions, SqlitePool};
use std::env;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
async fn main() {
dotenv().ok(); // load .env variables
// Logging
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.init();
// DB
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let db: SqlitePool = PoolOptions::new().connect(&database_url).await.unwrap();

View File

@ -3,4 +3,5 @@
rm -f db.sqlite
touch db.sqlite
sqlite3 db.sqlite < migration.sql
sqlite3 db.sqlite < seeds.sql