minor re-org and tidy

This commit is contained in:
Joe Ardent 2023-12-18 16:48:54 -08:00
parent eda946fa4c
commit dfbf605257
5 changed files with 33 additions and 38 deletions

View File

@ -1,6 +1,7 @@
use argon2::Argon2;
use async_trait::async_trait;
use axum_login::{AuthnBackend, UserId};
use axum_login::{AuthUser, AuthnBackend, UserId};
use julid::Julid;
use password_hash::{PasswordHash, PasswordVerifier};
use sqlx::SqlitePool;
use tower_sessions::{cookie::time::Duration, Expiry, SessionManagerLayer, SqliteStore};
@ -46,9 +47,7 @@ pub struct AuthError;
#[async_trait]
impl AuthnBackend for AuthStore {
type User = User;
type Credentials = Credentials;
type Error = AuthError;
async fn authenticate(
@ -57,9 +56,7 @@ impl AuthnBackend for AuthStore {
) -> Result<Option<Self::User>, Self::Error> {
let username = creds.username.trim();
let password = creds.password.trim();
let user = User::try_get(username, &self)
.await
.map_err(|_| AuthError)?;
let user = User::try_get(username, self).await.map_err(|_| AuthError)?;
let verifier = Argon2::default();
let hash = PasswordHash::new(&user.pwhash).map_err(|_| AuthError)?;
@ -79,6 +76,18 @@ impl AuthnBackend for AuthStore {
}
}
impl AuthUser for User {
type Id = Julid;
fn id(&self) -> Self::Id {
self.id
}
fn session_auth_hash(&self) -> &[u8] {
self.pwhash.as_bytes()
}
}
pub async fn session_layer(pool: SqlitePool) -> SessionManagerLayer<SqliteStore> {
let store = SqliteStore::new(pool);
store

View File

@ -3,9 +3,6 @@ use sqlx::SqlitePool;
#[macro_use]
extern crate justerror;
#[cfg(test)]
pub mod test_utils;
/// Some public interfaces for interacting with the database outside of the web
/// app
pub use db::get_db_pool;
@ -89,6 +86,9 @@ pub async fn app(db_pool: sqlx::SqlitePool) -> IntoMakeService<axum::Router> {
.into_make_service()
}
#[cfg(test)]
pub mod test_utils;
//-************************************************************************
// tests for the proc macro for optional user
//-************************************************************************

View File

@ -1,4 +1,3 @@
use axum::{
http::StatusCode,
response::{IntoResponse, Redirect, Response},
@ -6,7 +5,6 @@ use axum::{
};
use serde::{Deserialize, Serialize};
use crate::{auth::Credentials, AuthSession, LoginPage, LogoutPage, LogoutSuccessPage};
//-************************************************************************
@ -44,7 +42,7 @@ impl IntoResponse for LoginError {
}
// for receiving form submissions
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct LoginPostForm {
pub username: String,
pub password: String,
@ -52,10 +50,10 @@ pub struct LoginPostForm {
}
impl From<LoginPostForm> for Credentials {
fn from(value: LoginPostForm) -> Self {
fn from(form: LoginPostForm) -> Self {
Self {
username: value.username,
password: value.password,
username: form.username,
password: form.password,
}
}
}
@ -68,9 +66,10 @@ impl From<LoginPostForm> for Credentials {
#[axum::debug_handler]
pub async fn post_login(
mut auth: AuthSession,
Form(login): Form<LoginPostForm>,
Form(mut login_form): Form<LoginPostForm>,
) -> Result<impl IntoResponse, LoginError> {
let user = auth.authenticate(login.into()).await.map_err(|e| {
let dest = login_form.destination.take();
let user = auth.authenticate(login_form.into()).await.map_err(|e| {
tracing::debug!("{e}");
LoginErrorKind::Unknown
})?;
@ -81,7 +80,10 @@ pub async fn post_login(
auth.login(&user)
.await
.map_err(|_| LoginErrorKind::Internal)?;
Ok(Redirect::to("/"))
match dest {
Some(dest) => Ok(Redirect::to(&dest)),
_ => Ok(Redirect::to("/")),
}
}
_ => Err(LoginErrorKind::BadPassword.into()),
}

View File

@ -24,7 +24,6 @@ fn main() {
rt.block_on(async {
let addr: SocketAddr = ([0, 0, 0, 0], 3000).into();
tracing::debug!("binding to {addr:?}");
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
});

View File

@ -1,19 +1,15 @@
use std::{
fmt::{Debug, Display},
time::{SystemTime, UNIX_EPOCH},
};
use std::fmt::{Debug, Display};
use axum::{
extract::{Request, State},
middleware::Next,
response::IntoResponse,
};
use axum_login::AuthUser;
use julid::Julid;
use serde::{Deserialize, Serialize};
use sqlx::SqlitePool;
use crate::auth::AuthSession;
use crate::AuthSession;
const USERNAME_QUERY: &str = "select * from users where username = $1";
const LAST_SEEN_QUERY: &str = "update users set last_seen = (select unixepoch()) where id = $1";
@ -53,20 +49,8 @@ impl Display for User {
}
}
impl AuthUser for User {
type Id = Julid;
fn id(&self) -> Self::Id {
self.id
}
fn session_auth_hash(&self) -> &[u8] {
self.pwhash.as_bytes()
}
}
impl User {
pub async fn try_get(username: &str, db: &SqlitePool) -> Result<User, impl std::error::Error> {
pub async fn try_get(username: &str, db: &SqlitePool) -> Result<Self, impl std::error::Error> {
sqlx::query_as(USERNAME_QUERY)
.bind(username)
.fetch_one(db)
@ -98,6 +82,7 @@ pub async fn handle_update_last_seen(
request: Request,
next: Next,
) -> impl IntoResponse {
use std::time::{SystemTime, UNIX_EPOCH};
if let Some(user) = auth.user {
if let Some(then) = user.last_seen {
let now = SystemTime::now()