redirects weirdly

This commit is contained in:
Joe Ardent 2023-05-19 17:17:24 -07:00
parent ebfc759fa6
commit b7eb56e0e7
2 changed files with 61 additions and 11 deletions

View file

@ -22,7 +22,10 @@ async fn main() {
// build our application with some routes
let app = Router::new()
.route("/signup", get(get_create_user).post(post_create_user))
.route("/signup_success", get(get_signup_success))
.route(
"/signup_success",
get(get_signup_success).post(get_signup_success),
)
.with_state(pool);
tracing::debug!("binding to 0.0.0.0:3000");

View file

@ -1,4 +1,4 @@
use std::fmt::Display;
use std::{array, fmt::Display, ops::Deref};
use argon2::{
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
@ -10,7 +10,7 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use sqlx::SqlitePool;
use sqlx::{sqlite::SqliteRow, Row, SqlitePool};
use unicode_segmentation::UnicodeSegmentation;
use uuid::Uuid;
@ -19,12 +19,17 @@ use crate::templates::CreateUser;
const CREATE_QUERY: &str =
"insert into witches (id, username, displayname, email, pwhash) values ($1, $2, $3, $4, $5)";
#[derive(Debug, Clone, PartialEq, Eq)]
const ID_QUERY: &str = "select * from witches where id = $1";
const WITCH_SUCCESS_HEADER: &str = "X-Witch-Success";
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct User {
id: Uuid,
username: String,
displayname: Option<String>,
email: Option<String>,
last_seen: Option<i64>,
}
impl Display for User {
@ -40,13 +45,13 @@ impl Display for User {
}
}
#[derive(Debug, Clone, sqlx::FromRow, sqlx::Encode)]
#[derive(Debug, Default, Clone, sqlx::Encode)]
pub(crate) struct DbUser {
id: Uuid,
username: String,
displayname: Option<String>,
email: Option<String>,
last_seen: Option<u64>,
last_seen: Option<i64>,
pwhash: String,
}
@ -54,6 +59,27 @@ pub(crate) struct DbUser {
#[template(path = "signup_success.html")]
pub struct CreateUserSuccess(User);
impl sqlx::FromRow<'_, SqliteRow> for User {
fn from_row(row: &SqliteRow) -> Result<Self, sqlx::Error> {
let bytes: Vec<u8> = row.get("id");
let bytes = bytes.as_slice();
let bytes: [u8; 16] = bytes.try_into().unwrap();
let id = Uuid::from_bytes_le(bytes);
let username: String = row.get("username");
let displayname: Option<String> = row.get("displayname");
let last_seen: Option<i64> = row.get("last_seen");
let email: Option<String> = row.get("email");
Ok(Self {
id,
username,
displayname,
email,
last_seen,
})
}
}
impl From<DbUser> for User {
fn from(dbu: DbUser) -> Self {
User {
@ -61,6 +87,7 @@ impl From<DbUser> for User {
username: dbu.username,
displayname: dbu.displayname,
email: dbu.email,
last_seen: dbu.last_seen,
}
}
}
@ -124,20 +151,39 @@ pub async fn post_create_user(
tracing::debug!("created {user:?}");
let mut resp = axum::response::Redirect::temporary("/signup_success").into_response();
resp.headers_mut().append(
"X-Witch-Success",
WITCH_SUCCESS_HEADER,
user.id.simple().to_string().parse().unwrap(),
);
Ok(resp)
}
/// Get handler for successful signup; only meaningful
pub async fn get_signup_success(
headers: axum::http::HeaderMap,
State(pool): State<SqlitePool>,
) -> CreateUserSuccess {
if let Some(id) = headers.get("X-Witch") {
todo!()
) -> Response {
let user = if let Some(id) = headers.get(WITCH_SUCCESS_HEADER) {
let id = id.to_str().unwrap();
let id = Uuid::try_parse(id).unwrap_or_default();
let id_bytes = id.as_bytes();
sqlx::query_as(ID_QUERY)
.bind(id_bytes.as_slice())
.fetch_one(&pool)
.await
.unwrap_or_default()
} else {
User::default()
};
let mut resp = CreateUserSuccess(user.clone()).into_response();
if user.username.is_empty() {
// redirect to front page if we got here without a valid witch header
*resp.status_mut() = StatusCode::TEMPORARY_REDIRECT;
resp.headers_mut().insert("Location", "/".parse().unwrap());
}
todo!()
resp
}
async fn create_user(
@ -174,6 +220,7 @@ async fn create_user(
username: username.to_string(),
displayname: displayname.to_owned(),
email: email.to_owned(),
last_seen: None,
};
Ok(user)
}