Session data to change views

This commit is contained in:
Daniel Flanagan 2023-11-21 14:41:52 -06:00
parent 6579332013
commit 3f0fa57695
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
4 changed files with 56 additions and 33 deletions

View file

@ -2,7 +2,10 @@
// feather icons
pub const FEATHER_ICON_USER_PLUS: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user-plus"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="20" y1="8" x2="20" y2="14"></line><line x1="23" y1="11" x2="17" y2="11"></line></svg>"#;
#[allow(dead_code)]
pub const FEATHER_ICON_LAYOUT: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layout"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>"#;
pub const FEATHER_ICON_LOGIN: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-log-in"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line></svg>"#;
pub const FEATHER_ICON_USER: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>"#;
// pub const FEATHER_ICON_: &str = r#""#;

View file

@ -1,8 +1,10 @@
use axum_login::AuthSession;
use maud::{html, Markup, PreEscaped, DOCTYPE};
use crate::feather_icons;
use crate::{feather_icons, state};
pub fn header() -> Markup {
pub fn header(sess: &AuthSession<state::State>) -> Markup {
let is_logged_in = sess.user.is_some();
html! {
(DOCTYPE)
head {
@ -27,13 +29,24 @@ pub fn header() -> Markup {
// (PreEscaped(FEATHER_ICON_LAYOUT))
// "Dashboard"
// }
a href="/register" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_USER_PLUS))
"Register"
}
a href="/login" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_LOGIN))
"Login"
@if is_logged_in {
a href="/account" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_USER))
"Account"
}
a href="/app" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_LAYOUT))
"Dashboard"
}
} @else {
a href="/register" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_USER_PLUS))
"Register"
}
a href="/login" preload="" {
(PreEscaped(feather_icons::FEATHER_ICON_LOGIN))
"Login"
}
}
}
}

View file

@ -114,7 +114,7 @@ where
{
let password_bytes = password.as_ref().as_bytes();
let current = PasswordHash::new(current_digest.as_ref())?;
Ok(Argon2::default().verify_password(password_bytes, &current)?)
Argon2::default().verify_password(password_bytes, &current)
}
impl user::ActiveModel {}
@ -170,18 +170,16 @@ impl AuthnBackend for state::State {
type Error = AppError;
async fn authenticate(&self, l: Self::Credentials) -> Result<Option<Self::User>, Self::Error> {
match User::find()
Ok(User::find()
.filter(user::Column::Username.eq(l.username))
// TODO: will this have index problems since I'm searching over the password digest?
.one(&self.db)
.await?
{
Some(user) => match password_verify(&l.password, &user.password_digest) {
Ok(()) => Ok(Some(user)),
Err(e) => Err(e.into()),
},
None => Ok(None),
}
.filter(|u| {
password_verify(&l.password, &u.password_digest)
.ok()
.is_some()
}))
}
async fn get_user(&self, user_id: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {

View file

@ -10,6 +10,7 @@ use axum::{
response::{Html, IntoResponse},
};
use axum_csrf::CsrfToken;
use axum_login::AuthSession;
use maud::html;
use sea_orm::EntityTrait;
use tracing::instrument;
@ -24,11 +25,15 @@ where
type AppRes = Result<(StatusCode, Html<String>), AppError>;
#[instrument]
pub async fn index() -> Html<String> {
pub async fn index(sess: AuthSession<state::State>) -> Html<String> {
let is_logged_in = sess.user.is_some();
// let username = sess
// .user
// .map(|u| u.username)
// .unwrap_or_else(|| "N/A".to_owned());
Html(
html! {
(header())
(header(&sess))
main class="prose" {
h1 { "Manage live lyrics and music displays" }
p { "Stop struggling to share the same messy set of PowerPoint files or Google Presentations. Make editing and controlling your live lyrics and music displays easy and simple." }
@ -41,8 +46,12 @@ pub async fn index() -> Html<String> {
li { "Lightweight and fast" }
}
section class="flex gap" {
a href="/register" class="button bg-primary" { "Try now" }
a class="button" href="/login" { "Login" }
@if is_logged_in {
a href="/app" class="button bg-primary" { "Open app" }
} @else {
a href="/register" class="button bg-primary" { "Try now" }
a class="button" href="/login" { "Login" }
}
}
}
(footer())
@ -51,11 +60,11 @@ pub async fn index() -> Html<String> {
)
}
pub async fn register(t: CsrfToken) -> impl IntoResponse {
csrf(t, |token| {
pub async fn register(sess: AuthSession<state::State>, t: CsrfToken) -> impl IntoResponse {
csrf(t, move |token| {
Html(
html! {
(header())
(header(&sess))
main class="prose" {
h1 { "Register an account" }
form method="post" {
@ -79,11 +88,11 @@ pub async fn register(t: CsrfToken) -> impl IntoResponse {
.await
}
pub async fn login(t: CsrfToken) -> impl IntoResponse {
csrf(t, |token| {
pub async fn login(sess: AuthSession<state::State>, t: CsrfToken) -> impl IntoResponse {
csrf(t, move |token| {
Html(
html! {
(header())
(header(&sess))
main class="prose" {
h1 { "Login" }
form method="post" {
@ -107,20 +116,20 @@ pub async fn login(t: CsrfToken) -> impl IntoResponse {
.await
}
pub async fn all_users(State(s): State<state::State>) -> AppRes {
pub async fn all_users(sess: AuthSession<state::State>, State(s): State<state::State>) -> AppRes {
let users: Vec<user::Model> = User::find().all(&s.db).await?;
Ok((
StatusCode::OK,
Html(
html! {
(header())
(header(&sess))
main class="prose" {
h1 { "Users" }
ul {
@if users.is_empty() {
li { "It looks like there are no users yet!" }
} else {
} @else {
@for u in users {
li {
(u.username)