dummy auth

This commit is contained in:
Jovi Hsu 2021-11-04 00:03:35 +08:00
parent eb3271773a
commit c0868ff56a
12 changed files with 208 additions and 27 deletions

View File

@ -16,11 +16,14 @@ repository = "https://www.github.com/HsuJv/webgateway"
[dependencies]
actix = "0.10.0"
actix-session = "0.4"
actix-web = "3.3.2"
actix-files = "0.5.0"
tokio-tar = "0.3.0"
urlencoding = "2.1.0"
actix-web-actors = "3.0.0"
urlencoding = "2.1.0"
serde_json = "1.0"
rand = "0.8"
# log systems
femme = "1.3"
@ -31,8 +34,6 @@ async-log = "2.0.0"
panic = "unwind"
opt-level = 0
[profile.release]
panic = 'abort'
codegen-units = 1

View File

@ -1,10 +1,13 @@
use actix_files as fs;
use actix_session::CookieSession;
use actix_web::http::{ContentEncoding, StatusCode};
use actix_web::*;
use femme;
use log::info;
use rand::Rng;
mod user;
mod ws;
const STATIC_DIR: &str = "./static/";
@ -32,11 +35,14 @@ async fn main() -> std::io::Result<()> {
setup_logger();
info!("Server starts at http://127.0.0.1:8080");
let private_key = rand::thread_rng().gen::<[u8; 32]>();
HttpServer::new(move || {
App::new()
.wrap(CookieSession::signed(&private_key).secure(false))
.wrap(middleware::Compress::new(ContentEncoding::Gzip))
.service(index)
.service(web::resource("/ws").route(web::get().to(ws::index)))
.service(ws::ws_index)
.service(user::auth::auth)
.service(
fs::Files::new("/static", STATIC_DIR)
.prefer_utf8(true)

12
backend/src/user/auth.rs Normal file
View File

@ -0,0 +1,12 @@
use actix_web::*;
use serde_json::json;
use log::info;
#[post("/auth")]
pub async fn auth(req: HttpRequest) -> Result<HttpResponse, Error> {
info!("{:?}", req);
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(json!({"status": "success"})))
}

1
backend/src/user/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod auth;

View File

@ -1,4 +1,5 @@
use actix::{Actor, StreamHandler};
use actix_web::*;
use actix_web::{web, Error, HttpRequest, HttpResponse};
use actix_web_actors::ws;
use log::*;
@ -22,7 +23,8 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
}
}
pub async fn index(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
#[get("/ws")]
pub async fn ws_index(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
let resp = ws::start(MyWs {}, &req, stream);
match &resp {
Ok(resp) => info!("{:?}", resp),

View File

@ -31,6 +31,8 @@ console_error_panic_hook = { version = "0.1.6", optional = true }
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
wee_alloc = { version = "0.4", optional = true }
serde_json = "1.0"
anyhow = "1.0"
[features]
default = ["console_error_panic_hook", "wee_alloc"]

View File

@ -70,10 +70,8 @@ impl Component for App {
/>
</main>
<footer class="footer">
<div class="content has-text-centered">
{ "Powered by " }
<a href="https://yew.rs">{ "Yew" }</a>
</div>
{ "Powered by " }
<a href="https://yew.rs">{ "Yew" }</a>
</footer>
</>
}

View File

@ -0,0 +1,152 @@
use anyhow;
use serde_json::{json, Value};
use std::fmt::Debug;
use yew::services::{
fetch::{FetchTask, Request},
FetchService,
};
use yew::{format::Json, services::fetch::Response};
use yew::{prelude::*, services::ConsoleService};
pub enum AuthMsg {
UpdateUsername(String),
UpdatePassword(String),
AuthRequest,
AuthResponse(Result<Value, anyhow::Error>),
}
pub struct AuthComponents {
username: String,
password: String,
link: ComponentLink<Self>,
auth_result: String,
fetch_task: Option<FetchTask>,
}
impl Debug for AuthComponents {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"AuthComponents {{ username: {}, password: {} }}",
self.username, self.password
)
}
}
impl Component for AuthComponents {
type Message = AuthMsg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
AuthComponents {
username: String::new(),
password: String::new(),
auth_result: String::new(),
link,
fetch_task: None,
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
AuthMsg::UpdateUsername(username) => {
self.username = username;
self.auth_result.clear();
}
AuthMsg::UpdatePassword(password) => {
self.password = password;
self.auth_result.clear();
}
AuthMsg::AuthRequest => {
let auth_info = json!({
"username": self.username,
"password": self.password,
});
// 1. build the request
let request = Request::post("/auth")
.header("Content-Type", "application/json")
.body(Json(&auth_info))
.expect("Could not build auth request.");
// 2. construct a callback
let callback =
self.link
.callback(|response: Response<Json<Result<Value, anyhow::Error>>>| {
// ConsoleService::error(&format!("{:?}", response));
let Json(data) = response.into_body();
AuthMsg::AuthResponse(data)
});
// 3. pass the request and callback to the fetch service
let task = FetchService::fetch(request, callback).expect("failed to start request");
// 4. store the task so it isn't canceled immediately
self.fetch_task = Some(task);
}
AuthMsg::AuthResponse(response) => {
if let Ok(response) = response {
self.auth_result = response["status"].to_string();
} else {
self.auth_result = String::from("Auth failed with unknown reason");
ConsoleService::error(&format!("{:?}", response.unwrap_err().to_string()));
}
// release resources
self.fetch_task = None;
}
_ => panic!("unexpected message"),
}
// ConsoleService::log(&format!(
// "username: {}, password {}",
// self.username, self.password
// ));
true
}
fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
}
fn view(&self) -> Html {
let link = &self.link;
let update_uname = link.callback(|e: ChangeData| match e {
ChangeData::Value(val) => AuthMsg::UpdateUsername(val),
_ => panic!("unexpected message"),
});
let update_pword = link.callback(|e: ChangeData| match e {
ChangeData::Value(val) => AuthMsg::UpdatePassword(val),
_ => panic!("unexpected message"),
});
let auth_post = link.callback(|_| {
// ConsoleService::log("Auth post");
AuthMsg::AuthRequest
});
html! {
<div class="horizontal-centre vertical-centre">
<label for="username">{"Username: "}</label>
<input id="username" type="text" placeholder="Username" onchange={update_uname} />
<br />
<label for="password">{"Password: "}</label>
<input id="password" type="password" placeholder="Password" onchange={update_pword} />
<br />
<button type="submit" onclick={auth_post}>{"Login"}</button>
<br />
{self.auth_result_view()}
</div>
}
}
}
impl AuthComponents {
fn auth_result_view(&self) -> Html {
if let Some(_) = &self.fetch_task {
html! {
<div>{"Authing..."}</div>
}
} else {
html! {
<div>{self.auth_result.clone()}</div>
}
}
}
}

View File

@ -0,0 +1 @@
pub mod auth;

View File

@ -1,4 +1,5 @@
mod app;
mod components;
mod pages;
mod utils;

View File

@ -1,31 +1,26 @@
use yew::prelude::*;
use yew::Component;
use yew::ShouldRender;
use yew::{html, Component, Html};
pub struct PageHome;
use crate::components;
pub enum HomeMsg {}
pub struct PageHome {
link: ComponentLink<Self>,
}
impl Component for PageHome {
type Message = ();
type Message = HomeMsg;
type Properties = ();
fn create(_props: Self::Properties, _link: ComponentLink<Self>) -> Self {
Self
fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self { link }
}
fn view(&self) -> Html {
html! {
<section class="hero is-danger is-bold is-large">
<div class="hero-body">
<div class="container">
<h1 class="title">
{ "Hello World" }
</h1>
<h2 class="subtitle">
{ "Hello again" }
</h2>
</div>
</div>
</section>
<components::auth::AuthComponents/>
}
}

View File

@ -17,6 +17,16 @@
padding: 40px;
}
.horizontal-centre {
position: relative;
text-align: center;
}
.vertical-centre {
position: relative;
vertical-align: middle;
}
html,
body {
height: 100%;