Release: NX9-Auth v0.3.0
This commit is contained in:
1 parent
6a04d7f793
commit
d93f2cef95
92 files changed
+2418
-1143
No files matched your search
Generated
+19
-19
@@ -19,7 +19,7 @@ checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.2",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -668,9 +668,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "enumset"
|
||||
version = "1.1.13"
|
||||
version = "1.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "839c4174b41e75c8f7306110b2c51996a293b8d1d850edd529011841d9fede7d"
|
||||
checksum = "ccc5801fd11762e24d1e420d01d2ac518f2a2ca4329d4fbb6639f2412b6204e0"
|
||||
dependencies = [
|
||||
"enumset_derive",
|
||||
]
|
||||
@@ -955,9 +955,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
|
||||
checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@@ -1190,9 +1190,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.186"
|
||||
version = "0.2.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -1285,7 +1285,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nx9-auth-ui"
|
||||
version = "0.1.0"
|
||||
version = "0.3.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"console_error_panic_hook",
|
||||
@@ -1553,7 +1553,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.2",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1750,9 +1750,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.2"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1820,9 +1820,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.53.0"
|
||||
version = "1.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee"
|
||||
checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
@@ -2204,9 +2204,9 @@ checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
|
||||
|
||||
[[package]]
|
||||
name = "xxhash-rust"
|
||||
version = "0.8.17"
|
||||
version = "0.8.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985eec839aaf2a1270af8f4ebcf63cf9401cfd90f0902f97c28d9f104ffbde72"
|
||||
checksum = "aee1b19627c7c60102ab80d3a9cbe18de90bfe03bfa6c3715447681f0e8c8af6"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
@@ -2233,18 +2233,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.54"
|
||||
version = "0.8.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19"
|
||||
checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.54"
|
||||
version = "0.8.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
||||
checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
[package]
|
||||
name = "nx9-auth-ui"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
version = "0.3.0"
|
||||
edition = "2024"
|
||||
authors = ["NX9 Team", "Sunil Thakare"]
|
||||
description = "Dioxus web UI for nx9-auth IAM"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -28,10 +28,7 @@ pub fn LoginPage() -> Element {
|
||||
}
|
||||
});
|
||||
|
||||
let on_submit = move |evt: Event<FormData>| {
|
||||
// Critical: prevent native form submission (which defaults to GET
|
||||
// and would put credentials in the query string / browser history).
|
||||
evt.prevent_default();
|
||||
let mut handle_submit = move || {
|
||||
if loading() {
|
||||
return;
|
||||
}
|
||||
@@ -43,6 +40,7 @@ pub fn LoginPage() -> Element {
|
||||
return;
|
||||
}
|
||||
|
||||
let _ = web_sys::console::log_1(&"[nx9-auth-ui] Submitting login request...".into());
|
||||
loading.set(true);
|
||||
error.set(None);
|
||||
let mut auth = state.auth;
|
||||
@@ -51,8 +49,10 @@ pub fn LoginPage() -> Element {
|
||||
let mut password = password;
|
||||
let nav = nav.clone();
|
||||
spawn(async move {
|
||||
let _ = web_sys::console::log_1(&"[nx9-auth-ui] Executing api::login...".into());
|
||||
match api::login(&u, &p).await {
|
||||
Ok(login) => {
|
||||
let _ = web_sys::console::log_1(&"[nx9-auth-ui] Login succeeded".into());
|
||||
// Clear password from UI memory after successful submit.
|
||||
password.set(String::new());
|
||||
|
||||
@@ -125,6 +125,7 @@ pub fn LoginPage() -> Element {
|
||||
nav.replace(Route::DashboardPage {});
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = web_sys::console::warn_1(&format!("[nx9-auth-ui] Login failed: {e:?}").into());
|
||||
// Map API errors to a safe, non-enumerating message for creds.
|
||||
let msg = match e {
|
||||
api::ApiError::Unauthorized
|
||||
@@ -153,6 +154,16 @@ pub fn LoginPage() -> Element {
|
||||
});
|
||||
};
|
||||
|
||||
let on_form_submit = move |evt: Event<FormData>| {
|
||||
evt.prevent_default();
|
||||
handle_submit();
|
||||
};
|
||||
|
||||
let on_button_click = move |evt: Event<MouseData>| {
|
||||
evt.prevent_default();
|
||||
handle_submit();
|
||||
};
|
||||
|
||||
rsx! {
|
||||
div { class: "auth-page",
|
||||
div { class: "auth-card",
|
||||
@@ -170,13 +181,11 @@ pub fn LoginPage() -> Element {
|
||||
div { class: "alert alert-error", role: "alert", "{err}" }
|
||||
}
|
||||
|
||||
// method="post" is mandatory: HTML default is GET, which would
|
||||
// put credentials in the URL if preventDefault failed.
|
||||
// SPA form submission via WASM fetch() only (Content-Type: application/json).
|
||||
// Both form onsubmit and button onclick trigger handle_submit with prevent_default.
|
||||
form {
|
||||
method: "post",
|
||||
action: "#",
|
||||
autocomplete: "on",
|
||||
onsubmit: on_submit,
|
||||
onsubmit: on_form_submit,
|
||||
TextInput {
|
||||
label: "Username",
|
||||
name: "username",
|
||||
@@ -198,6 +207,7 @@ pub fn LoginPage() -> Element {
|
||||
class: "btn btn-primary",
|
||||
r#type: "submit",
|
||||
style: "width: 100%; margin-top: 0.5rem;",
|
||||
onclick: on_button_click,
|
||||
disabled: loading() || username().trim().is_empty() || password().is_empty(),
|
||||
if loading() {
|
||||
span { class: "spinner", style: "width:14px;height:14px;border-width:2px;" }
|
||||
|
||||
@@ -61,7 +61,7 @@ fn client() -> Client {
|
||||
|
||||
/// Attach credentials + optional bearer session token.
|
||||
fn authorize(builder: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
|
||||
// let builder = builder.fetch_credentials_include();
|
||||
let builder = builder.fetch_credentials_include();
|
||||
if let Some(token) = session::load_access_token() {
|
||||
builder.header("Authorization", format!("Bearer {token}"))
|
||||
} else {
|
||||
@@ -180,6 +180,7 @@ pub async fn login(username: &str, password: &str) -> Result<LoginResponse, ApiE
|
||||
let url = api_url("/auth/login");
|
||||
let resp = client()
|
||||
.post(&url)
|
||||
.fetch_credentials_include()
|
||||
.header("Accept", "application/json")
|
||||
.header("Content-Type", "application/json")
|
||||
.json(&body)
|
||||
|
||||
@@ -74,12 +74,14 @@ impl BootstrapState {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn has_any_permission(&self, perms: &[&str]) -> bool {
|
||||
self.me()
|
||||
.map(|m| perms.iter().any(|p| m.permissions.iter().any(|x| x == p)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_adminish(&self) -> bool {
|
||||
self.has_any_permission(&[
|
||||
"roles:manage",
|
||||
|
||||
Reference in new issue
Block a user