Skip to main content

upub_web/components/
login.rs

1use 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						// update our username and token cookies
57						userid_tx.set(Some(auth_response.user));
58						token_tx.set(Some(auth_response.token));
59						// clear caches: we may see things differently now that we're logged in!
60						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}