Merge branch 'maybemaybeuser'

This commit is contained in:
Joe Ardent 2023-06-13 15:57:12 -07:00
commit 46f52ff7ee
8 changed files with 147 additions and 13 deletions

9
Cargo.lock generated
View file

@ -1166,6 +1166,14 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "optional_optional_user"
version = "0.1.0"
dependencies = [
"quote",
"syn 2.0.18",
]
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -2373,6 +2381,7 @@ dependencies = [
"axum-macros", "axum-macros",
"axum-test", "axum-test",
"justerror", "justerror",
"optional_optional_user",
"password-hash", "password-hash",
"rand_core", "rand_core",
"serde", "serde",

View file

@ -25,6 +25,9 @@ axum-login = { version = "0.5", features = ["sqlite", "sqlx"] }
unicode-segmentation = "1" unicode-segmentation = "1"
async-session = "3" async-session = "3"
# proc macros:
optional_optional_user = {path = "optional_optional_user"}
[dev-dependencies] [dev-dependencies]
axum-test = "9.0.0" axum-test = "9.0.0"

46
optional_optional_user/Cargo.lock generated Normal file
View file

@ -0,0 +1,46 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "maybe_optional_user"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"

View file

@ -0,0 +1,11 @@
[package]
name = "optional_optional_user"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.28"
syn = "2.0.18"

View file

@ -0,0 +1,40 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemStruct};
#[proc_macro_derive(OptionalOptionalUser)]
pub fn derive_optional_optional_user(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
let name = &input.ident;
let has_user = input
.fields
.iter()
.find(|f| {
if let Some(ident) = f.ident.clone() {
ident == "user"
} else {
false
}
})
.is_some();
let has_option = if has_user {
quote!(
::std::any::TypeId::of::<::std::option::Option<crate::User>>() == self.user.type_id()
)
} else {
quote!(false)
};
let output = quote!(
impl crate::templates::OptionalOptionalUser for #name {
fn has_optional_user(&self) -> bool {
use ::std::any::Any;
#has_user && #has_option
}
}
);
TokenStream::from(output)
}

View file

@ -1,9 +1,14 @@
use askama::Template; use askama::Template;
use optional_optional_user::OptionalOptionalUser;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::User; use crate::User;
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] pub trait OptionalOptionalUser {
fn has_optional_user(&self) -> bool;
}
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "signup.html")] #[template(path = "signup.html")]
pub struct CreateUser { pub struct CreateUser {
pub username: String, pub username: String,
@ -13,7 +18,9 @@ pub struct CreateUser {
pub pw_verify: String, pub pw_verify: String,
} }
#[derive(Debug, Clone, Template, Default, Deserialize, Serialize, PartialEq, Eq)] #[derive(
Debug, Clone, Template, Default, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser,
)]
#[template(path = "signup_success.html")] #[template(path = "signup_success.html")]
pub struct CreateUserSuccess(pub User); pub struct CreateUserSuccess(pub User);
@ -24,23 +31,38 @@ pub struct LoginPost {
pub password: String, pub password: String,
} }
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "login_get.html")] #[template(path = "login_get.html")]
pub struct LoginGet { pub struct LoginGet {
pub username: String, pub username: String,
pub password: String, pub password: String,
} }
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "logout_get.html")] #[template(path = "logout_get.html")]
pub struct LogoutGet; pub struct LogoutGet;
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "logout_post.html")] #[template(path = "logout_post.html")]
pub struct LogoutPost; pub struct LogoutPost;
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "index.html")] #[template(path = "index.html")]
pub struct MainPage { pub struct MainPage {
pub user: Option<User>, pub user: Option<User>,
} }
#[cfg(test)]
mod test {
use super::*;
#[test]
fn main_page_has_optional_user() {
assert!(MainPage::default().has_optional_user());
}
#[test]
fn signup_success_has_no_optional_user() {
assert!(!CreateUserSuccess::default().has_optional_user());
}
}

View file

@ -1,15 +1,16 @@
use askama::Template; use askama::Template;
use optional_optional_user::OptionalOptionalUser;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{User, Watch}; use crate::{templates::OptionalOptionalUser, User, Watch};
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "get_watches.html")] #[template(path = "get_watches.html")]
pub struct GetWatches { pub struct GetWatches {
pub watches: Vec<Watch>, pub watches: Vec<Watch>,
pub user: Option<User>, pub user: Option<User>,
} }
#[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Default, Template, Deserialize, Serialize, PartialEq, Eq, OptionalOptionalUser)]
#[template(path = "get_search_watches.html")] #[template(path = "get_search_watches.html")]
pub struct GetSearchWatches {} pub struct GetSearchWatches {}

View file

@ -1,6 +1,7 @@
{% if self.has_optional_user() %}
{% match user %} {% match user %}
{% when Some with (usr) %} {% when Some with (usr) %}
<div class="header_logged_in"> <div class="header_logged_in">
Hello, {{ usr.username }}! Hello, {{ usr.username }}!
</div> </div>
@ -8,13 +9,14 @@
<input type="submit" value="sign out?"> <input type="submit" value="sign out?">
</form> </form>
</div> </div>
{% else %} {% else %}
<div class="header_logged_out"> <div class="header_logged_out">
Heya, why don't you <a href="/login">log in</a> or <a href="/signup">sign up</a>? Heya, why don't you <a href="/login">log in</a> or <a href="/signup">sign up</a>?
</div> </div>
{% endmatch %} {% endmatch %}
{% else %}
{% endif %}
<hr/> <hr/>