redirects weirdly
This commit is contained in:
parent
ebfc759fa6
commit
b7eb56e0e7
2 changed files with 61 additions and 11 deletions
|
@ -22,7 +22,10 @@ async fn main() {
|
||||||
// build our application with some routes
|
// build our application with some routes
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/signup", get(get_create_user).post(post_create_user))
|
.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);
|
.with_state(pool);
|
||||||
|
|
||||||
tracing::debug!("binding to 0.0.0.0:3000");
|
tracing::debug!("binding to 0.0.0.0:3000");
|
||||||
|
|
67
src/users.rs
67
src/users.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::fmt::Display;
|
use std::{array, fmt::Display, ops::Deref};
|
||||||
|
|
||||||
use argon2::{
|
use argon2::{
|
||||||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||||
|
@ -10,7 +10,7 @@ use axum::{
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::{sqlite::SqliteRow, Row, SqlitePool};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -19,12 +19,17 @@ use crate::templates::CreateUser;
|
||||||
const CREATE_QUERY: &str =
|
const CREATE_QUERY: &str =
|
||||||
"insert into witches (id, username, displayname, email, pwhash) values ($1, $2, $3, $4, $5)";
|
"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 {
|
pub struct User {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
username: String,
|
username: String,
|
||||||
displayname: Option<String>,
|
displayname: Option<String>,
|
||||||
email: Option<String>,
|
email: Option<String>,
|
||||||
|
last_seen: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for User {
|
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 {
|
pub(crate) struct DbUser {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
username: String,
|
username: String,
|
||||||
displayname: Option<String>,
|
displayname: Option<String>,
|
||||||
email: Option<String>,
|
email: Option<String>,
|
||||||
last_seen: Option<u64>,
|
last_seen: Option<i64>,
|
||||||
pwhash: String,
|
pwhash: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +59,27 @@ pub(crate) struct DbUser {
|
||||||
#[template(path = "signup_success.html")]
|
#[template(path = "signup_success.html")]
|
||||||
pub struct CreateUserSuccess(User);
|
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 {
|
impl From<DbUser> for User {
|
||||||
fn from(dbu: DbUser) -> Self {
|
fn from(dbu: DbUser) -> Self {
|
||||||
User {
|
User {
|
||||||
|
@ -61,6 +87,7 @@ impl From<DbUser> for User {
|
||||||
username: dbu.username,
|
username: dbu.username,
|
||||||
displayname: dbu.displayname,
|
displayname: dbu.displayname,
|
||||||
email: dbu.email,
|
email: dbu.email,
|
||||||
|
last_seen: dbu.last_seen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,20 +151,39 @@ pub async fn post_create_user(
|
||||||
tracing::debug!("created {user:?}");
|
tracing::debug!("created {user:?}");
|
||||||
let mut resp = axum::response::Redirect::temporary("/signup_success").into_response();
|
let mut resp = axum::response::Redirect::temporary("/signup_success").into_response();
|
||||||
resp.headers_mut().append(
|
resp.headers_mut().append(
|
||||||
"X-Witch-Success",
|
WITCH_SUCCESS_HEADER,
|
||||||
user.id.simple().to_string().parse().unwrap(),
|
user.id.simple().to_string().parse().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(resp)
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get handler for successful signup; only meaningful
|
||||||
pub async fn get_signup_success(
|
pub async fn get_signup_success(
|
||||||
headers: axum::http::HeaderMap,
|
headers: axum::http::HeaderMap,
|
||||||
State(pool): State<SqlitePool>,
|
State(pool): State<SqlitePool>,
|
||||||
) -> CreateUserSuccess {
|
) -> Response {
|
||||||
if let Some(id) = headers.get("X-Witch") {
|
let user = if let Some(id) = headers.get(WITCH_SUCCESS_HEADER) {
|
||||||
todo!()
|
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(
|
async fn create_user(
|
||||||
|
@ -174,6 +220,7 @@ async fn create_user(
|
||||||
username: username.to_string(),
|
username: username.to_string(),
|
||||||
displayname: displayname.to_owned(),
|
displayname: displayname.to_owned(),
|
||||||
email: email.to_owned(),
|
email: email.to_owned(),
|
||||||
|
last_seen: None,
|
||||||
};
|
};
|
||||||
Ok(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue