Release: NX9-Auth v0.3.0

This commit is contained in:
thakares committed 2026-07-22 19:36:22 +05:30
1 parent 6a04d7f793
commit d93f2cef95
92 files changed
+2418 -1143

No files matched your search

Generated
+19 -19
View File
@@ -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
View File
@@ -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]
+19 -9
View File
@@ -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;" }
+2 -1
View File
@@ -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)
+2
View File
@@ -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",