Pass username/password to the server and allow login failure
This commit is contained in:
parent
c94105acc3
commit
c21054814c
@ -11,3 +11,12 @@ pub struct ChatMessage {
|
||||
pub struct LoggedInResponse {
|
||||
pub logged_in: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct LoginRequest {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct LoginResponse(pub Result<(), String>);
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::components::Nav;
|
||||
use common::LoggedInResponse;
|
||||
use common::{LoggedInResponse, LoginRequest, LoginResponse};
|
||||
use gloo::{
|
||||
console::{error, log},
|
||||
history::{BrowserHistory, History},
|
||||
net::http::Request,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use web_sys::HtmlInputElement;
|
||||
use yew::{platform::spawn_local, prelude::*};
|
||||
use yew_hooks::use_mount;
|
||||
|
||||
@ -24,7 +26,10 @@ impl Default for LoginQuery {
|
||||
#[function_component]
|
||||
#[allow(non_snake_case)] // Component names should be in PascalCase
|
||||
pub fn Login() -> Html {
|
||||
let username_ref = use_node_ref();
|
||||
let password_ref = use_node_ref();
|
||||
let disable_input = use_state(|| false);
|
||||
let login_error = use_state(|| None);
|
||||
let query_params = BrowserHistory::new()
|
||||
.location()
|
||||
.query::<LoginQuery>()
|
||||
@ -33,9 +38,16 @@ pub fn Login() -> Html {
|
||||
let login_submitted = {
|
||||
let disable_input = disable_input.clone();
|
||||
let redirect = redirect.clone();
|
||||
let username_ref = username_ref.clone();
|
||||
let password_ref = password_ref.clone();
|
||||
let login_error = login_error.clone();
|
||||
move || {
|
||||
disable_input.set(true);
|
||||
let disable_input = disable_input.clone();
|
||||
let redirect = redirect.clone();
|
||||
let username_ref = username_ref.clone();
|
||||
let password_ref = password_ref.clone();
|
||||
let login_error = login_error.clone();
|
||||
spawn_local(async move {
|
||||
let location = web_sys::window().unwrap().location();
|
||||
let login_url = format!(
|
||||
@ -43,13 +55,40 @@ pub fn Login() -> Html {
|
||||
location.protocol().unwrap(),
|
||||
location.host().unwrap()
|
||||
);
|
||||
Request::post(&login_url)
|
||||
.body("")
|
||||
let username = username_ref.cast::<HtmlInputElement>().unwrap().value();
|
||||
let password = password_ref.cast::<HtmlInputElement>().unwrap().value();
|
||||
let req_body = LoginRequest { username, password };
|
||||
let resp = match Request::post(&login_url)
|
||||
.json(&req_body)
|
||||
.unwrap()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
BrowserHistory::new().push(&redirect);
|
||||
{
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
error!(format!("Could not send login request to server: {err}"));
|
||||
login_error.set(Some("Error logging in".to_string()));
|
||||
disable_input.set(false);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let LoginResponse(resp) = match resp.json().await {
|
||||
Ok(val) => val,
|
||||
Err(err) => {
|
||||
error!(format!("Could not parse login response: {err}"));
|
||||
login_error.set(Some("Error logging in".to_string()));
|
||||
disable_input.set(false);
|
||||
return;
|
||||
}
|
||||
};
|
||||
match resp {
|
||||
Ok(_) => BrowserHistory::new().push(&redirect),
|
||||
Err(err) => {
|
||||
login_error.set(Some(err));
|
||||
password_ref.cast::<HtmlInputElement>().unwrap().set_value("");
|
||||
disable_input.set(false);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -92,20 +131,25 @@ pub fn Login() -> Html {
|
||||
style="max-width: 570px"
|
||||
>
|
||||
<h1>{ "Login" }</h1>
|
||||
if login_error.is_some() {
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{ login_error.as_ref().unwrap() }
|
||||
</div>
|
||||
}
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
class="form-control"
|
||||
placeholder="Username"
|
||||
disabled={*disable_input}
|
||||
ref={username_ref}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
class="form-control"
|
||||
placeholder="Password"
|
||||
disabled={*disable_input}
|
||||
onkeydown={password_keypress}
|
||||
ref={password_ref}
|
||||
/>
|
||||
if !*disable_input {
|
||||
<input
|
||||
|
@ -9,7 +9,7 @@ use axum::{async_trait, Json};
|
||||
use axum::{routing::get, Router};
|
||||
use axum_login::{AuthManagerLayerBuilder, AuthSession, AuthUser, AuthnBackend, UserId};
|
||||
use clap::Parser;
|
||||
use common::{ChatMessage, LoggedInResponse};
|
||||
use common::{ChatMessage, LoggedInResponse, LoginRequest, LoginResponse};
|
||||
use futures::stream::SplitSink;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use slab::Slab;
|
||||
@ -124,11 +124,20 @@ async fn serve_index(static_dir: &Path) -> Response {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn login(mut auth_session: AuthSession<DummyAuthBackend>) -> Response {
|
||||
async fn login(
|
||||
mut auth_session: AuthSession<DummyAuthBackend>,
|
||||
Json(req): Json<LoginRequest>,
|
||||
) -> Response {
|
||||
if req.username != "pjht" || req.password != "123456" {
|
||||
return Json(LoginResponse(Err(
|
||||
"Invalid username or password".to_string()
|
||||
)))
|
||||
.into_response();
|
||||
}
|
||||
if auth_session.login(&DummyAuthUser).await.is_err() {
|
||||
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||
}
|
||||
StatusCode::OK.into_response()
|
||||
Json(LoginResponse(Ok(()))).into_response()
|
||||
}
|
||||
|
||||
async fn logout(mut auth_session: AuthSession<DummyAuthBackend>) -> Response {
|
||||
|
Loading…
Reference in New Issue
Block a user