End-to-end web-based signup, login, and logout flows work.
This commit is contained in:
parent
113982ba27
commit
d2613b0ef9
8 changed files with 95 additions and 15 deletions
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
15
src/login.rs
15
src/login.rs
|
@ -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
|
||||
}
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -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 = {
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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
26
templates/index.html
Normal 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
13
templates/logout_get.html
Normal 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 %}
|
11
templates/logout_post.html
Normal file
11
templates/logout_post.html
Normal 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 %}
|
Loading…
Reference in a new issue