Session data to change views
This commit is contained in:
parent
6579332013
commit
3f0fa57695
4 changed files with 56 additions and 33 deletions
|
@ -2,7 +2,10 @@
|
||||||
// feather icons
|
// 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>"#;
|
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_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_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#""#;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use axum_login::AuthSession;
|
||||||
use maud::{html, Markup, PreEscaped, DOCTYPE};
|
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! {
|
html! {
|
||||||
(DOCTYPE)
|
(DOCTYPE)
|
||||||
head {
|
head {
|
||||||
|
@ -27,6 +29,16 @@ pub fn header() -> Markup {
|
||||||
// (PreEscaped(FEATHER_ICON_LAYOUT))
|
// (PreEscaped(FEATHER_ICON_LAYOUT))
|
||||||
// "Dashboard"
|
// "Dashboard"
|
||||||
// }
|
// }
|
||||||
|
@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="" {
|
a href="/register" preload="" {
|
||||||
(PreEscaped(feather_icons::FEATHER_ICON_USER_PLUS))
|
(PreEscaped(feather_icons::FEATHER_ICON_USER_PLUS))
|
||||||
"Register"
|
"Register"
|
||||||
|
@ -40,6 +52,7 @@ pub fn header() -> Markup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn footer() -> Markup {
|
pub fn footer() -> Markup {
|
||||||
|
|
|
@ -114,7 +114,7 @@ where
|
||||||
{
|
{
|
||||||
let password_bytes = password.as_ref().as_bytes();
|
let password_bytes = password.as_ref().as_bytes();
|
||||||
let current = PasswordHash::new(current_digest.as_ref())?;
|
let current = PasswordHash::new(current_digest.as_ref())?;
|
||||||
Ok(Argon2::default().verify_password(password_bytes, ¤t)?)
|
Argon2::default().verify_password(password_bytes, ¤t)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl user::ActiveModel {}
|
impl user::ActiveModel {}
|
||||||
|
@ -170,18 +170,16 @@ impl AuthnBackend for state::State {
|
||||||
type Error = AppError;
|
type Error = AppError;
|
||||||
|
|
||||||
async fn authenticate(&self, l: Self::Credentials) -> Result<Option<Self::User>, Self::Error> {
|
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))
|
.filter(user::Column::Username.eq(l.username))
|
||||||
// TODO: will this have index problems since I'm searching over the password digest?
|
// TODO: will this have index problems since I'm searching over the password digest?
|
||||||
.one(&self.db)
|
.one(&self.db)
|
||||||
.await?
|
.await?
|
||||||
{
|
.filter(|u| {
|
||||||
Some(user) => match password_verify(&l.password, &user.password_digest) {
|
password_verify(&l.password, &u.password_digest)
|
||||||
Ok(()) => Ok(Some(user)),
|
.ok()
|
||||||
Err(e) => Err(e.into()),
|
.is_some()
|
||||||
},
|
}))
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_user(&self, user_id: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {
|
async fn get_user(&self, user_id: &UserId<Self>) -> Result<Option<Self::User>, Self::Error> {
|
||||||
|
|
33
src/views.rs
33
src/views.rs
|
@ -10,6 +10,7 @@ use axum::{
|
||||||
response::{Html, IntoResponse},
|
response::{Html, IntoResponse},
|
||||||
};
|
};
|
||||||
use axum_csrf::CsrfToken;
|
use axum_csrf::CsrfToken;
|
||||||
|
use axum_login::AuthSession;
|
||||||
use maud::html;
|
use maud::html;
|
||||||
use sea_orm::EntityTrait;
|
use sea_orm::EntityTrait;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
@ -24,11 +25,15 @@ where
|
||||||
|
|
||||||
type AppRes = Result<(StatusCode, Html<String>), AppError>;
|
type AppRes = Result<(StatusCode, Html<String>), AppError>;
|
||||||
|
|
||||||
#[instrument]
|
pub async fn index(sess: AuthSession<state::State>) -> Html<String> {
|
||||||
pub async fn index() -> 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(
|
||||||
html! {
|
html! {
|
||||||
(header())
|
(header(&sess))
|
||||||
main class="prose" {
|
main class="prose" {
|
||||||
h1 { "Manage live lyrics and music displays" }
|
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." }
|
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,21 +46,25 @@ pub async fn index() -> Html<String> {
|
||||||
li { "Lightweight and fast" }
|
li { "Lightweight and fast" }
|
||||||
}
|
}
|
||||||
section class="flex gap" {
|
section class="flex gap" {
|
||||||
|
@if is_logged_in {
|
||||||
|
a href="/app" class="button bg-primary" { "Open app" }
|
||||||
|
} @else {
|
||||||
a href="/register" class="button bg-primary" { "Try now" }
|
a href="/register" class="button bg-primary" { "Try now" }
|
||||||
a class="button" href="/login" { "Login" }
|
a class="button" href="/login" { "Login" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
(footer())
|
(footer())
|
||||||
}
|
}
|
||||||
.into_string(),
|
.into_string(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn register(t: CsrfToken) -> impl IntoResponse {
|
pub async fn register(sess: AuthSession<state::State>, t: CsrfToken) -> impl IntoResponse {
|
||||||
csrf(t, |token| {
|
csrf(t, move |token| {
|
||||||
Html(
|
Html(
|
||||||
html! {
|
html! {
|
||||||
(header())
|
(header(&sess))
|
||||||
main class="prose" {
|
main class="prose" {
|
||||||
h1 { "Register an account" }
|
h1 { "Register an account" }
|
||||||
form method="post" {
|
form method="post" {
|
||||||
|
@ -79,11 +88,11 @@ pub async fn register(t: CsrfToken) -> impl IntoResponse {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(t: CsrfToken) -> impl IntoResponse {
|
pub async fn login(sess: AuthSession<state::State>, t: CsrfToken) -> impl IntoResponse {
|
||||||
csrf(t, |token| {
|
csrf(t, move |token| {
|
||||||
Html(
|
Html(
|
||||||
html! {
|
html! {
|
||||||
(header())
|
(header(&sess))
|
||||||
main class="prose" {
|
main class="prose" {
|
||||||
h1 { "Login" }
|
h1 { "Login" }
|
||||||
form method="post" {
|
form method="post" {
|
||||||
|
@ -107,20 +116,20 @@ pub async fn login(t: CsrfToken) -> impl IntoResponse {
|
||||||
.await
|
.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?;
|
let users: Vec<user::Model> = User::find().all(&s.db).await?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
Html(
|
Html(
|
||||||
html! {
|
html! {
|
||||||
(header())
|
(header(&sess))
|
||||||
main class="prose" {
|
main class="prose" {
|
||||||
h1 { "Users" }
|
h1 { "Users" }
|
||||||
ul {
|
ul {
|
||||||
@if users.is_empty() {
|
@if users.is_empty() {
|
||||||
li { "It looks like there are no users yet!" }
|
li { "It looks like there are no users yet!" }
|
||||||
} else {
|
} @else {
|
||||||
@for u in users {
|
@for u in users {
|
||||||
li {
|
li {
|
||||||
(u.username)
|
(u.username)
|
||||||
|
|
Loading…
Reference in a new issue