Merge branch 'maybemaybeuser'
This commit is contained in:
commit
46f52ff7ee
8 changed files with 147 additions and 13 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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
46
optional_optional_user/Cargo.lock
generated
Normal 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"
|
11
optional_optional_user/Cargo.toml
Normal file
11
optional_optional_user/Cargo.toml
Normal 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"
|
40
optional_optional_user/src/lib.rs
Normal file
40
optional_optional_user/src/lib.rs
Normal 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)
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
|
@ -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/>
|
||||||
|
|
Loading…
Reference in a new issue