minor re-org and tidy
This commit is contained in:
parent
eda946fa4c
commit
dfbf605257
5 changed files with 33 additions and 38 deletions
21
src/auth.rs
21
src/auth.rs
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//-************************************************************************
|
||||
|
|
20
src/login.rs
20
src/login.rs
|
@ -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()),
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
23
src/users.rs
23
src/users.rs
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue