upub_web/components/
login.rs1use leptos::prelude::*;
2use crate::prelude::*;
3
4#[component]
5pub fn LoginBox(
6 token_tx: WriteSignal<Option<String>>,
7 userid_tx: WriteSignal<Option<String>>,
8) -> impl IntoView {
9 let auth = use_context::<Auth>().expect("missing auth context");
10 let username_ref: NodeRef<leptos::html::Input> = NodeRef::new();
11 let password_ref: NodeRef<leptos::html::Input> = NodeRef::new();
12 view! {
13 <div>
14 <div class="w-100" class:hidden=move || !auth.present() >
15 "hi "<a href={move || Uri::web(U::Actor, &auth.username() )} >{move || auth.username() }</a>
16 <input style="float:right" type="submit" value="logout" on:click=move |_| {
17 token_tx.set(None);
18 crate::cache::OBJECTS.clear();
19 crate::cache::TIMELINES.clear();
20 crate::cache::WEBFINGER.clear();
21 } />
22 </div>
23 <div class:hidden=move || auth.present() >
24 <form on:submit=move|ev| {
25 ev.prevent_default();
26 tracing::info!("logging in...");
27 let email = username_ref.get().map(|x| x.value()).unwrap_or("".into());
28 let password = password_ref.get().map(|x| x.value()).unwrap_or("".into());
29 leptos::task::spawn_local(async move {
30 let res = match crate::Http::request::<LoginForm>(
31 reqwest::Method::POST,
32 &format!("{URL_BASE}/auth"),
33 Some(&LoginForm { email, password }),
34 auth,
35 ).await {
36 Ok(res) => res,
37 Err(e) => {
38 tracing::warn!("could not login: {e}");
39 if let Some(rf) = password_ref.get() {
40 rf.set_value("")
41 };
42 return
43 }
44 };
45 let auth_response = match res.json::<AuthResponse>().await {
46 Ok(r) => r,
47 Err(e) => {
48 tracing::warn!("could not deserialize token response: {e}");
49 if let Some(rf) = password_ref.get() {
50 rf.set_value("")
51 };
52 return
53 },
54 };
55 tracing::info!("logged in until {}", auth_response.expires);
56 userid_tx.set(Some(auth_response.user));
58 token_tx.set(Some(auth_response.token));
59 crate::cache::OBJECTS.clear();
61 crate::cache::TIMELINES.clear();
62 crate::cache::WEBFINGER.clear();
63 });
64 } >
65 <table class="w-100 align">
66 <tr>
67 <td colspan="2"><input class="w-100" type="text" node_ref=username_ref placeholder="username" /></td>
68 </tr>
69 <tr>
70 <td colspan="2"><input class="w-100" type="password" node_ref=password_ref placeholder="password" /></td>
71 </tr>
72 <tr>
73 <td class="w-50"><input class="w-100" type="submit" value="login" /></td>
74 <td class="w-50"><a href="/web/register"><input class="w-100" type="button" value="register" /></a></td>
75 </tr>
76 </table>
77 </form>
78 </div>
79 </div>
80 }
81}
82
83
84#[derive(Debug, serde::Serialize)]
85struct LoginForm {
86 email: String,
87 password: String,
88}
89
90
91#[derive(Debug, Clone, serde::Deserialize)]
92pub struct AuthResponse {
93 pub token: String,
94 pub user: String,
95 pub expires: chrono::DateTime<chrono::Utc>,
96}