Allow to login with OIDC

This commit is contained in:
traxys 2023-07-27 00:06:36 +02:00
parent f556fec3bb
commit 7a2ff7ad1d
12 changed files with 782 additions and 29 deletions

View file

@ -6,7 +6,7 @@ use api::{
LoginResponse, UserInfo,
};
use dioxus::prelude::*;
use dioxus_router::{use_router, Route, Router};
use dioxus_router::{use_route, use_router, Redirect, Route, Router};
use gloo_storage::{errors::StorageError, LocalStorage, Storage};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
@ -33,6 +33,11 @@ const API_ROUTE: &str = match option_env!("REGALADE_API_SERVER_BASE") {
Some(v) => v,
};
const FRONTEND_ROOT: &str = match option_env!("REGALADE_FRONTEND_DOMAIN") {
None => "http://localhost:8080",
Some(v) => v,
};
#[macro_export]
macro_rules! api {
($($arg:tt)*) => {{
@ -204,6 +209,37 @@ async fn do_login(username: String, password: String) -> anyhow::Result<()> {
Ok(())
}
async fn check_oidc() -> anyhow::Result<bool> {
let rsp = gloo_net::http::Request::get(api!("login/has_oidc"))
.send()
.await?;
Ok(rsp.status() == 200)
}
fn Openid(cx: Scope) -> Element {
let has = use_future(cx, (), |()| check_oidc());
cx.render(match has.value().unwrap_or(&Ok(false)) {
Ok(true) => {
let route = api!("login/oidc").to_owned();
let ret = urlencoding::encode(&format!("{FRONTEND_ROOT}/login/oidc")).to_string();
rsx! {
a {
href: "{route}?return={ret}",
class: "mt-1 w-100 btn btn-lg btn-primary",
"Login with OpenID"
}
}
}
Ok(false) => rsx! {{}},
Err(e) => {
log::error!("Could not check oidc status: {e:?}");
rsx! {{}}
}
})
}
fn Login(cx: Scope) -> Element {
let error = use_state(cx, || None::<String>);
let router = use_router(cx);
@ -256,6 +292,7 @@ fn Login(cx: Scope) -> Element {
label { "for": "floatingPass", "Password" }
}
button { class: "w-100 btn btn-lg btn-primary", "type": "submit", "Login" }
Openid {}
}
})
}
@ -505,9 +542,38 @@ fn Index(cx: Scope) -> Element {
cx.render(rsx! {"INDEX"})
}
#[derive(Deserialize)]
struct OidcQuery {
token: String,
username: String,
}
fn OidcRedirect(cx: Scope) -> Element {
let auth = use_route(cx).query::<OidcQuery>();
cx.render(match auth {
None => rsx! {"No authentication query, internal error."},
Some(v) => {
match LocalStorage::set(
"token",
LoginInfo {
token: v.token,
name: v.username,
},
) {
Ok(_) => {
gloo_utils::window().location().replace("/").unwrap();
rsx! {{}}
}
Err(_) => rsx! {"Could not store authentication, try again."},
}
}
})
}
fn App(cx: Scope) -> Element {
cx.render(rsx! {
Router {
Router {
Route { to: Page::Home.to(),
RegaladeSidebar { current: Page::Home, Index {} }
}
@ -524,6 +590,7 @@ fn App(cx: Scope) -> Element {
RegaladeSidebar { current: Page::RecipeList, recipe::RecipeView {} }
}
Route { to: "/login", Login {} }
Route { to: "/login/oidc", OidcRedirect {} }
Route { to: "/household_selection",
LoginRedirect { HouseholdSelection {} }
}