End-to-end web-based signup, login, and logout flows work.

This commit is contained in:
Joe Ardent 2023-05-29 14:25:50 -07:00
parent 113982ba27
commit d2613b0ef9
8 changed files with 95 additions and 15 deletions

View file

@ -1,15 +1,19 @@
use axum::response::{IntoResponse, Redirect};
use crate::AuthContext;
use crate::{templates::Index, AuthContext};
pub async fn handle_slash_redir() -> impl IntoResponse {
Redirect::temporary("/")
}
pub async fn handle_slash(auth: AuthContext) -> impl IntoResponse {
if let Some(user) = auth.current_user {
tracing::debug!("Logged in as: {user}");
if let Some(ref user) = auth.current_user {
let name = &user.username;
tracing::debug!("Logged in as: {name}");
} else {
tracing::debug!("Not logged in.")
tracing::debug!("Not logged in.");
}
Index {
user: auth.current_user,
}
}

View file

@ -11,7 +11,7 @@ use axum::{
use sqlx::SqlitePool;
use crate::{
templates::{LoginGet, LoginPost},
templates::{LoginGet, LoginPost, LogoutGet, LogoutPost},
util::form_decode,
AuthContext, User,
};
@ -41,12 +41,12 @@ pub enum LoginErrorKind {
impl IntoResponse for LoginError {
fn into_response(self) -> Response {
match self.0 {
LoginErrorKind::Unknown => (
LoginErrorKind::Unknown | LoginErrorKind::Internal => (
StatusCode::INTERNAL_SERVER_ERROR,
"An unknown error occurred; you cursed, brah?",
)
.into_response(),
_ => (StatusCode::BAD_REQUEST, format!("{self}")).into_response(),
_ => (StatusCode::OK, format!("{self}")).into_response(),
}
}
}
@ -99,9 +99,12 @@ pub async fn get_login() -> impl IntoResponse {
}
pub async fn get_logout() -> impl IntoResponse {
todo!()
LogoutGet
}
pub async fn post_logout() -> impl IntoResponse {
todo!()
pub async fn post_logout(mut auth: AuthContext) -> impl IntoResponse {
if auth.current_user.is_some() {
auth.logout().await;
}
LogoutPost
}

View file

@ -1,7 +1,10 @@
use std::net::SocketAddr;
use std::{net::SocketAddr, time::Duration};
use axum::{routing::get, Router};
use axum_login::{axum_sessions::SessionLayer, AuthLayer, SqliteStore};
use axum_login::{
axum_sessions::{PersistencePolicy, SessionLayer},
AuthLayer, SqliteStore,
};
use rand_core::{OsRng, RngCore};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use witch_watch::{
@ -26,7 +29,7 @@ async fn main() {
let pool = db::get_pool().await;
let secret = {
let mut bytes = [0u8; 128];
let mut bytes = [0u8; 64];
let mut rng = OsRng;
rng.fill_bytes(&mut bytes);
bytes
@ -35,7 +38,10 @@ async fn main() {
let session_layer = {
let store = SqliteSessionStore::from_client(pool.clone());
store.migrate().await.expect("Could not migrate session DB");
SessionLayer::new(store, &secret).with_secure(true)
SessionLayer::new(store, &secret)
.with_secure(true)
.with_persistence_policy(PersistencePolicy::ExistingOnly)
.with_session_ttl(Some(Duration::from_secs(3600 * 24 * 366)))
};
let auth_layer = {

View file

@ -1,6 +1,8 @@
use askama::Template;
use serde::{Deserialize, Serialize};
use crate::User;
#[derive(Debug, Default, Template, Deserialize, Serialize)]
#[template(path = "signup.html")]
pub struct CreateUser {
@ -24,3 +26,17 @@ pub struct LoginGet {
pub username: String,
pub password: String,
}
#[derive(Debug, Default, Template, Deserialize, Serialize)]
#[template(path = "logout_get.html")]
pub struct LogoutGet;
#[derive(Debug, Default, Template, Deserialize, Serialize)]
#[template(path = "logout_post.html")]
pub struct LogoutPost;
#[derive(Debug, Default, Template, Deserialize, Serialize)]
#[template(path = "index.html")]
pub struct Index {
pub user: Option<User>,
}

View file

@ -1,12 +1,13 @@
use std::fmt::Display;
use axum_login::{secrecy::SecretVec, AuthUser};
use serde::{Deserialize, Serialize};
use sqlx::SqlitePool;
use uuid::Uuid;
const USERNAME_QUERY: &str = "select * from witches where username = $1";
#[derive(Debug, Default, Clone, PartialEq, Eq, sqlx::FromRow)]
#[derive(Debug, Default, Clone, PartialEq, Eq, sqlx::FromRow, Serialize, Deserialize)]
pub struct User {
pub id: Uuid,
pub username: String,

26
templates/index.html Normal file
View file

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block title %}Welcome to Witch Watch, Bish{% endblock %}
{% block content %}
<h1>Welcome to Witch Watch</h1>
{% match user %}
{% when Some with (usr) %}
<p>
Hello, {{ usr.username }}! It's nice to see you.
</p>
</br>
<p>
<form action="/logout" enctype="application/x-www-form-urlencoded" method="post">
<input type="submit" value="sign out?">
</form>
</p>
{% else %}
<p>
Heya, why don't you <a href="/login">log in</a> or <a href="/signup">sign up</a>?
</p>
{% endmatch %}
{% endblock %}

13
templates/logout_get.html Normal file
View file

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% block title %}Logout of Witch Watch, Bish{% endblock %}
{% block content %}
<p>
<form action="/logout" enctype="application/x-www-form-urlencoded" method="post">
<input type="submit" value="Sign out">
</form>
</p>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block title %}Thanks for Signing Up for Witch Watch, Bish{% endblock %}
{% block content %}
<h1>Goodbye</h1>
<p>Good bye! May we suggest checking out <a href="/">our home page</a>?</p>
{% endblock %}