diff --git a/.codespell_ignore b/.codespell_ignore new file mode 100644 index 000000000..3f1bc3ad0 --- /dev/null +++ b/.codespell_ignore @@ -0,0 +1,11 @@ +alledges +crate +unexpect +Pres +pres +ACI +aci +ser +te +ue +unx \ No newline at end of file diff --git a/.gitignore b/.gitignore index 28a59475b..a757a9df9 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ kanidm-client-tools.tar.gz .coverage pykanidm/dist/ pykanidm/site/ + +# oauth2 integration test things +scripts/oauth_proxy/client.secret +scripts/oauth_proxy/envfile diff --git a/Cargo.lock b/Cargo.lock index 669dddcfa..fa957f254 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2259,7 +2259,7 @@ dependencies = [ "gloo-render", "gloo-storage", "gloo-timers 0.2.6", - "gloo-utils", + "gloo-utils 0.1.7", "gloo-worker", ] @@ -2269,7 +2269,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "wasm-bindgen", @@ -2316,7 +2316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" dependencies = [ "gloo-events", - "gloo-utils", + "gloo-utils 0.1.7", "serde", "serde-wasm-bindgen 0.5.0", "serde_urlencoded", @@ -2334,7 +2334,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-sink", - "gloo-utils", + "gloo-utils 0.1.7", "http", "js-sys", "pin-project", @@ -2362,7 +2362,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "serde_json", @@ -2406,6 +2406,19 @@ dependencies = [ "web-sys", ] +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "gloo-worker" version = "0.2.1" @@ -2415,7 +2428,7 @@ dependencies = [ "anymap2", "bincode", "gloo-console", - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "wasm-bindgen", @@ -3059,6 +3072,7 @@ dependencies = [ "filetime", "futures", "futures-util", + "hashbrown 0.14.2", "http", "hyper", "kanidm_build_profiles", @@ -3196,13 +3210,85 @@ dependencies = [ ] [[package]] -name = "kanidmd_web_ui" +name = "kanidmd_web_ui_admin" +version = "1.1.0-rc.14-dev" +dependencies = [ + "gloo", + "gloo-utils 0.2.0", + "js-sys", + "kanidm_proto", + "kanidmd_web_ui_shared", + "lazy_static", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "time", + "url", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "web-sys", + "yew", + "yew-router", +] + +[[package]] +name = "kanidmd_web_ui_login_flows" +version = "1.1.0-rc.14-dev" +dependencies = [ + "gloo", + "gloo-utils 0.2.0", + "js-sys", + "kanidm_proto", + "kanidmd_web_ui_shared", + "lazy_static", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "time", + "url", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "web-sys", + "yew", + "yew-router", +] + +[[package]] +name = "kanidmd_web_ui_shared" +version = "1.1.0-rc.14-dev" +dependencies = [ + "gloo", + "js-sys", + "kanidm_proto", + "lazy_static", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_json", + "time", + "url", + "uuid", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test", + "web-sys", + "yew", + "yew-router", +] + +[[package]] +name = "kanidmd_web_ui_user" version = "1.1.0-rc.14-dev" dependencies = [ "gloo", "gloo-timers 0.3.0", + "gloo-utils 0.2.0", "js-sys", "kanidm_proto", + "kanidmd_web_ui_shared", "lazy_static", "qrcode", "regex", @@ -4088,6 +4174,7 @@ dependencies = [ "fixedbitset", "indexmap 2.0.2", "serde", + "serde_derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 37ff37123..6de5cd5f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,10 @@ members = [ "unix_integration", "unix_integration/nss_kanidm", "unix_integration/pam_kanidm", - "server/web_ui", + "server/web_ui/admin", + "server/web_ui/login_flows", + "server/web_ui/user", + "server/web_ui/shared", "server/daemon", "server/lib", "server/lib-macros", @@ -125,6 +128,7 @@ futures-concurrency = "^3.1.0" futures-util = { version = "^0.3.21", features = ["sink"] } gix = { version = "0.53.1", default-features = false } gloo = "^0.8.1" +gloo-utils = "0.2.0" hashbrown = { version = "0.14.2", features = ["serde", "inline-more", "ahash"] } hex = "^0.4.3" http = "0.2.9" @@ -138,6 +142,7 @@ image = { version = "0.24.7", default-features = false, features = [ ] } enum-iterator = "1.4.0" js-sys = "^0.3.63" +kanidmd_web_ui_shared = { path = "./server/web_ui/shared" } # REMOVE this lazy_static = "^1.4.0" ldap3_client = "^0.3.5" diff --git a/Makefile b/Makefile index 25cf2d38b..d250c3a44 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,7 @@ install-tools: codespell: ## spell-check things. codespell: codespell -c \ - -L 'crate,unexpect,Pres,pres,ACI,aci,ser,te,ue,unx,aNULL' \ + --ignore-words .codespell_ignore \ --skip='./target,./pykanidm/.venv,./pykanidm/.mypy_cache,./.mypy_cache,./pykanidm/poetry.lock' \ --skip='./book/*.js' \ --skip='./book/book/*' \ @@ -141,7 +141,10 @@ codespell: --skip='./docs/*,./.git' \ --skip='*.svg' \ --skip='./rlm_python/mods-available/eap' \ - --skip='./server/web_ui/static/external,./server/web_ui/pkg/external' \ + --skip='./server/web_ui/static/external' \ + --skip='./server/web_ui/pkg/external' \ + --skip='./server/web_ui/shared/static/external' \ + --skip='./server/web_ui/admin/static/external,./server/web_ui/admin/pkg/external' \ --skip='./server/lib/src/constants/system_config.rs,./pykanidm/site,./server/lib/src/constants/*.json' .PHONY: test/pykanidm/pytest @@ -277,7 +280,7 @@ cert/clean: .PHONY: webui webui: ## Build the WASM web frontend - cd server/web_ui && ./build_wasm_release.sh + cd server/web_ui && ./build_wasm.sh .PHONY: webui/test webui/test: ## Run wasm-pack test diff --git a/book/src/DEVELOPER_README.md b/book/src/DEVELOPER_README.md index bef424db9..2c0193bed 100644 --- a/book/src/DEVELOPER_README.md +++ b/book/src/DEVELOPER_README.md @@ -276,7 +276,7 @@ cd server/web_ui/ ./build_wasm_dev.sh ``` -To build for release, run `build_wasm_release.sh`. +To build for release, run `build_wasm.sh`, or `make webui` from the project root. The "developer" profile for kanidmd will automatically use the pkg output in this folder. diff --git a/libs/client/src/lib.rs b/libs/client/src/lib.rs index 81c194d76..25f742707 100644 --- a/libs/client/src/lib.rs +++ b/libs/client/src/lib.rs @@ -24,6 +24,7 @@ use std::os::unix::fs::MetadataExt; use std::path::Path; use std::time::Duration; +use kanidm_proto::constants::uri::V1_AUTH_VALID; use kanidm_proto::constants::{APPLICATION_JSON, ATTR_NAME, KOPID, KSESSIONID, KVERSION}; use kanidm_proto::v1::*; use reqwest::header::CONTENT_TYPE; @@ -1442,7 +1443,7 @@ impl KanidmClient { } pub async fn auth_valid(&self) -> Result<(), ClientError> { - self.perform_get_request("/v1/auth/valid").await + self.perform_get_request(V1_AUTH_VALID).await } pub async fn whoami(&self) -> Result, ClientError> { diff --git a/libs/crypto/Cargo.toml b/libs/crypto/Cargo.toml index 079dd1b54..a6a16f4a5 100644 --- a/libs/crypto/Cargo.toml +++ b/libs/crypto/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kanidm_lib_crypto" version = "0.1.0" -edition = "2021" +edition = { workspace = true } [features] tpm = ["dep:tss-esapi"] diff --git a/libs/file_permissions/Cargo.toml b/libs/file_permissions/Cargo.toml index 97d73e817..ef08b2602 100644 --- a/libs/file_permissions/Cargo.toml +++ b/libs/file_permissions/Cargo.toml @@ -17,7 +17,7 @@ doctest = false [dependencies] [target.'cfg(target_family = "windows")'.dependencies] -whoami = {workspace = true} +whoami = { workspace = true } [target.'cfg(not(target_family = "windows"))'.dependencies] kanidm_utils_users = { workspace = true } diff --git a/proto/src/constants.rs b/proto/src/constants.rs index 2e397c1b3..912bee3b1 100644 --- a/proto/src/constants.rs +++ b/proto/src/constants.rs @@ -1,4 +1,6 @@ //! Because consistency is great! +//! +pub mod uri; pub const CONTENT_TYPE_JPG: &str = "image/jpeg"; pub const CONTENT_TYPE_PNG: &str = "image/png"; @@ -6,7 +8,7 @@ pub const CONTENT_TYPE_GIF: &str = "image/gif"; pub const CONTENT_TYPE_SVG: &str = "image/svg+xml"; pub const CONTENT_TYPE_WEBP: &str = "image/webp"; -// for when the user uploads things to the various image endpoints +// For when the user uploads things to the various image endpoints, these are the valid content-types. pub const VALID_IMAGE_UPLOAD_CONTENT_TYPES: [&str; 5] = [ CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, @@ -22,13 +24,14 @@ pub const DEFAULT_CLIENT_CONFIG_PATH: &str = "/etc/kanidm/config"; /// The user-owned path for Kanidm client config pub const DEFAULT_CLIENT_CONFIG_PATH_HOME: &str = "~/.config/kanidm"; -/// The default bind address for the Kanidm server +/// The default HTTPS bind address for the Kanidm server pub const DEFAULT_SERVER_ADDRESS: &str = "127.0.0.1:8443"; pub const DEFAULT_SERVER_LOCALHOST: &str = "localhost:8443"; +/// The default LDAP bind address for the Kanidm server pub const DEFAULT_LDAP_ADDRESS: &str = "127.0.0.1:636"; pub const DEFAULT_LDAP_LOCALHOST: &str = "localhost:636"; -/// IF YOU CHANGE THESE VALUES YOU BREAK EVERYTHING +// IF YOU CHANGE THESE VALUES YOU BREAK EVERYTHING pub const ATTR_ACCOUNT_EXPIRE: &str = "account_expire"; pub const ATTR_ACCOUNT_VALID_FROM: &str = "account_valid_from"; pub const ATTR_ACCOUNT: &str = "account"; @@ -185,15 +188,18 @@ pub const LDAP_ATTR_OBJECTCLASS: &str = "objectClass"; pub const LDAP_ATTR_OU: &str = "ou"; pub const LDAP_CLASS_GROUPOFNAMES: &str = "groupofnames"; -// rust can't deal with this being compiled out, don't try and #[cfg()] them +// Rust can't deal with this being compiled out, don't try and #[cfg()] them pub const TEST_ATTR_NON_EXIST: &str = "non-exist"; pub const TEST_ATTR_TEST_ATTR: &str = "testattr"; pub const TEST_ATTR_EXTRA: &str = "extra"; pub const TEST_ATTR_NUMBER: &str = "testattrnumber"; pub const TEST_ATTR_NOTALLOWED: &str = "notallowed"; +/// HTTP Header containing an auth session ID for when you're going through an auth flow pub const KSESSIONID: &str = "X-KANIDM-AUTH-SESSION-ID"; +/// HTTP Header containing the backend operation ID pub const KOPID: &str = "X-KANIDM-OPID"; +/// HTTP Header containing the Kanidm server version pub const KVERSION: &str = "X-KANIDM-VERSION"; pub const X_FORWARDED_FOR: &str = "x-forwarded-for"; diff --git a/proto/src/constants/uri.rs b/proto/src/constants/uri.rs new file mode 100644 index 000000000..3474d4323 --- /dev/null +++ b/proto/src/constants/uri.rs @@ -0,0 +1,16 @@ +//! Shared URIs +//! +//! ⚠️ ⚠️ WARNING ⚠️ ⚠️ +//! +//! IF YOU CHANGE THESE VALUES YOU MUST UPDATE OIDC DISCOVERY URLS EVERYWHERE +//! +//! SERIOUSLY... DO NOT CHANGE THEM! +//! +/// ⚠️ ⚠️ WARNING DO NOT CHANGE THIS ⚠️ ⚠️ +pub const OAUTH2_AUTHORISE: &str = "/oauth2/authorise"; +/// ⚠️ ⚠️ WARNING DO NOT CHANGE THIS ⚠️ ⚠️ +pub const OAUTH2_AUTHORISE_PERMIT: &str = "/oauth2/authorise/permit"; +/// ⚠️ ⚠️ WARNING DO NOT CHANGE THIS ⚠️ ⚠️ +pub const OAUTH2_AUTHORISE_REJECT: &str = "/oauth2/authorise/reject"; + +pub const V1_AUTH_VALID: &str = "/v1/auth/valid"; diff --git a/scripts/oauth_proxy/README.md b/scripts/oauth_proxy/README.md new file mode 100644 index 000000000..0036743ba --- /dev/null +++ b/scripts/oauth_proxy/README.md @@ -0,0 +1,9 @@ +# OAuth Proxy Test + +This dir has some things for setting up a simple OAuth2 RS so things can get tested. + +## Quick Setup + +1. Run the `setup_dev_environment.sh` script and set a credential for `testuser`. +2. Look for the OAuth2 Secret in the script output and copy it into a file called `client.secret` in this dir. +3. Run `./run_proxy.sh` to start the proxy, and then go to the URL and do the thing! diff --git a/scripts/oauth_proxy/index.html b/scripts/oauth_proxy/index.html new file mode 100644 index 000000000..b82af1e8d --- /dev/null +++ b/scripts/oauth_proxy/index.html @@ -0,0 +1,12 @@ + + + OAuth Test Proxy + + +

Success!

+ +

You have successfully authenticated with the OAuth proxy.

+ +

🦀Crabs🦀 and 🎂Cakes🎂 for everyone!

+ + diff --git a/scripts/oauth_proxy/run_proxy.sh b/scripts/oauth_proxy/run_proxy.sh new file mode 100755 index 000000000..876eeeccb --- /dev/null +++ b/scripts/oauth_proxy/run_proxy.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +PROXY_VERSION="7-debian-11" +PROXY_HTTP_PORT="10080" +PROXY_HTTPS_PORT="10443" +CLIENT_ID="test_oauth2" + +# documentation for proxy settings is here: https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#environment-variables + +# generate a cookie secret +echo "OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -hex 16)" > envfile +{ + echo "OAUTH2_PROXY_CLIENT_ID=${CLIENT_ID}" + echo "OAUTH2_PROXY_CLIENT_SECRET_FILE=/opt/client.secret" + echo "OAUTH2_PROXY_COOKIE_EXPIRE=300s" + echo "OAUTH2_PROXY_CODE_CHALLENGE_METHOD=S256" + echo "OAUTH2_PROXY_COOKIE_CSRF_EXPIRE=300s" + echo "OAUTH2_PROXY_HTTP_ADDRESS=:${PROXY_HTTP_PORT}" + echo "OAUTH2_PROXY_HTTPS_ADDRESS=:${PROXY_HTTPS_PORT}" + echo "OAUTH2_PROXY_PROVIDER=oidc" + echo "OAUTH2_PROXY_SCOPE=openid" + echo "OAUTH2_PROXY_EMAIL_DOMAIN=example.com" + echo "OAUTH2_PROXY_UPSTREAM=file://opt/index.html" + echo "OAUTH2_PROXY_OIDC_ISSUER_URL=https://localhost:8443/oauth2/openid/${CLIENT_ID}" + echo "OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY=true" + # cert things, loads the certs that we use for for the test server + echo "OAUTH2_PROXY_TLS_CERT_FILE=/opt/cert.pem" + echo "OAUTH2_PROXY_TLS_KEY_FILE=/opt/key.pem" + + } >> envfile + +if [ ! -f client.secret ]; then + echo "The client.secret file is missing! Can't run!" + exit 1 +fi + +if [ -z "$(cat client.secret)" ]; then + echo "The client.secret file is empty! Can't run!" + exit 1 +fi + +echo "#################################################################" +echo " Starting the proxy" +echo " Access it on https://localhost:${PROXY_HTTPS_PORT}" +echo "#################################################################" + +docker run --rm -it \ + --env-file envfile \ + --network host \ + --mount "type=bind,source=/tmp/kanidm/cert.pem,target=/opt/cert.pem" \ + --mount "type=bind,source=/tmp/kanidm/key.pem,target=/opt/key.pem" \ + --mount "type=bind,source=./index.html,target=/opt/index.html" \ + --mount "type=bind,source=./client.secret,target=/opt/client.secret" \ + "bitnami/oauth2-proxy:${PROXY_VERSION}" --email-domain='*' diff --git a/scripts/setup_dev_environment.sh b/scripts/setup_dev_environment.sh index f0b746ae6..48aa2384b 100755 --- a/scripts/setup_dev_environment.sh +++ b/scripts/setup_dev_environment.sh @@ -24,8 +24,12 @@ if [ "${1}" == "--help" ]; then exit 0 fi if [ ! -f run_insecure_dev_server.sh ]; then - echo "Please run from the server/daemon dir!" - exit 1 + if [ "$(basename "$(pwd)")" == "kanidm" ]; then + cd server/daemon || exit 1 + else + echo "Please run from the server/daemon dir, I can't tell where you are..." + exit 1 + fi fi @@ -115,22 +119,32 @@ ${KANIDM} group add-members "${TEST_GROUP}" "${TEST_USER_NAME}" -D idm_admin echo "Enable experimental UI for admin idm_admin ${TEST_USER_NAME}" ${KANIDM} group add-members idm_ui_enable_experimental_features admin idm_admin "${TEST_USER_NAME}" -D idm_admin -# create oauth2 rp -echo "Creating the OAuth2 RP" -${KANIDM} system oauth2 create "${OAUTH2_RP_ID}" "${OAUTH2_RP_DISPLAY}" "https://kanidm.com" -D admin +# create oauth2 rp for kanidm.com +echo "Creating the kanidm.com OAuth2 RP" +${KANIDM} system oauth2 create "kanidm_com" "Kanidm.com" "https://kanidm.com" -D admin +echo "Creating the kanidm.com OAuth2 RP Scope Map" +${KANIDM} system oauth2 update-scope-map "kanidm_com" "${TEST_GROUP}" openid -D admin +echo "Creating the kanidm.com OAuth2 RP Supplemental Scope Map" +${KANIDM} system oauth2 update-sup-scope-map "kanidm_com" "${TEST_GROUP}" admin -D admin -echo "Creating the OAuth2 RP Scope Map" + +# create oauth2 rp for localhost:10443 - for oauth2 proxy testing +echo "Creating the ${OAUTH2_RP_ID} OAuth2 RP" +${KANIDM} system oauth2 create "${OAUTH2_RP_ID}" "${OAUTH2_RP_DISPLAY}" "https://localhost:10443" -D admin +echo "Creating the ${OAUTH2_RP_ID} OAuth2 RP Scope Map - Group ${TEST_GROUP}" ${KANIDM} system oauth2 update-scope-map "${OAUTH2_RP_ID}" "${TEST_GROUP}" openid -D admin -echo "Creating the OAuth2 RP Supplemental Scope Map" +echo "Creating the ${OAUTH2_RP_ID} OAuth2 RP Supplemental Scope Map" ${KANIDM} system oauth2 update-sup-scope-map "${OAUTH2_RP_ID}" "${TEST_GROUP}" admin -D admin + echo "Creating the OAuth2 RP Secondary Supplemental Crab-baite Scope Map.... wait, no that's not a thing." echo "Checking the OAuth2 RP Exists" ${KANIDM} system oauth2 list -D admin | rg -A10 "${OAUTH2_RP_ID}" # config auth2 -echo "Pulling secret for the OAuth2 RP" -${KANIDM} system oauth2 show-basic-secret -o json "${OAUTH2_RP_ID}" -D admin +echo "Pulling secret for the ${OAUTH2_RP_ID} OAuth2 RP" +OAUTH2_SECRET="$(${KANIDM} system oauth2 show-basic-secret -o json "${OAUTH2_RP_ID}" -D admin)" +echo "${OAUTH2_SECRET}" echo "Creating cred reset link for ${TEST_USER_NAME}" ${KANIDM} person credential create-reset-token "${TEST_USER_NAME}" -D idm_admin @@ -141,4 +155,6 @@ echo "###################################" echo "admin password: ${ADMIN_PASS}" echo "idm_admin password: ${IDM_ADMIN_PASS}" echo "UI URL: ${KANIDM_URL}" +echo "OAuth2 RP ID: ${OAUTH2_RP_ID}" +echo "OAuth2 Secret: $(echo "${OAUTH2_SECRET}" | jq -r .secret)" echo "###################################" diff --git a/server/core/Cargo.toml b/server/core/Cargo.toml index a110c3f98..643c0abcd 100644 --- a/server/core/Cargo.toml +++ b/server/core/Cargo.toml @@ -29,6 +29,7 @@ cron = { workspace = true } filetime = { workspace = true } futures = { workspace = true } futures-util = { workspace = true } +hashbrown = { workspace = true } http = { workspace = true } hyper = { workspace = true } kanidm_proto = { workspace = true } diff --git a/server/core/src/https/javascript.rs b/server/core/src/https/javascript.rs index 121cafcbc..343cebae4 100644 --- a/server/core/src/https/javascript.rs +++ b/server/core/src/https/javascript.rs @@ -43,15 +43,15 @@ pub struct JavaScriptFile { impl JavaScriptFile { /// returns a `"#, - self.filepath, &self.hash, &typeattr, + r#""#, + self.filepath, &self.hash, &filetype, ) } } diff --git a/server/core/src/https/middleware/caching.rs b/server/core/src/https/middleware/caching.rs index 0303ff33d..45b60e7e9 100644 --- a/server/core/src/https/middleware/caching.rs +++ b/server/core/src/https/middleware/caching.rs @@ -20,7 +20,7 @@ pub async fn dont_cache_me(request: Request, next: Next) -> Response { response } -/// Adds `no-cache max-age=0` to the response headers. +/// Adds a cache control header of 300 seconds to the response headers. pub async fn cache_me(request: Request, next: Next) -> Response { let mut response = next.run(request).await; let cache_header = CacheControl::new() diff --git a/server/core/src/https/mod.rs b/server/core/src/https/mod.rs index 20193271e..53f425bf4 100644 --- a/server/core/src/https/mod.rs +++ b/server/core/src/https/mod.rs @@ -26,6 +26,7 @@ use axum::Router; use axum_csp::{CspDirectiveType, CspValue}; use axum_macros::FromRef; use compact_jwt::{Jws, JwsSigner, JwsUnverified}; +use hashbrown::HashMap; use http::{HeaderMap, HeaderValue}; use hyper::server::accept::Accept; use hyper::server::conn::{AddrStream, Http}; @@ -62,7 +63,7 @@ pub struct ServerState { pub jws_signer: compact_jwt::JwsSigner, pub jws_validator: compact_jwt::JwsValidator, // The SHA384 hashes of javascript files we're going to serve to users - pub js_files: Vec, + pub js_files: JavaScriptFiles, pub(crate) trust_x_forward_for: bool, pub csp_header: HeaderValue, } @@ -90,51 +91,80 @@ impl ServerState { } } -pub fn get_js_files(role: ServerRole) -> Vec { - let mut js_files: Vec = Vec::new(); +#[derive(Clone)] +pub struct JavaScriptFiles { + all_pages: Vec, + selected: HashMap, +} + +pub fn get_js_files(role: ServerRole) -> Result { + let mut all_pages: Vec = Vec::new(); + let mut selected: HashMap = HashMap::new(); if !matches!(role, ServerRole::WriteReplicaNoUI) { // let's set up the list of js module hashes - { - let filepath = "wasmloader.js"; + for filepath in [ + "wasmloader_admin.js", + "wasmloader_login_flows.js", + "wasmloader_user.js", + ] { match generate_integrity_hash(format!( "{}/{}", env!("KANIDM_WEB_UI_PKG_PATH").to_owned(), filepath, )) { - Ok(hash) => js_files.push(JavaScriptFile { - filepath, - hash, - filetype: Some("module".to_string()), - }), + Ok(hash) => { + selected.insert( + filepath.to_string(), + JavaScriptFile { + filepath, + hash, + filetype: Some("module".to_string()), + }, + ); + } Err(err) => { - admin_error!(?err, "Failed to generate integrity hash for wasmloader.js") + admin_error!( + ?err, + "Failed to generate integrity hash for {} - cancelling startup!", + filepath + ); + return Err(()); } }; } - // let's set up the list of non-module hashes - { - let filepath = "external/bootstrap.bundle.min.js"; + + for (filepath, filetype) in [ + ("shared.js", Some("module".to_string())), + ("external/bootstrap.bundle.min.js", None), + ] { + // let's set up the list of non-wasm-module js files we want to serve + // for filepath in ["external/bootstrap.bundle.min.js", "shared.js"] { match generate_integrity_hash(format!( "{}/{}", env!("KANIDM_WEB_UI_PKG_PATH").to_owned(), filepath, )) { - Ok(hash) => js_files.push(JavaScriptFile { + Ok(hash) => all_pages.push(JavaScriptFile { filepath, hash, - filetype: None, + filetype, }), Err(err) => { admin_error!( ?err, - "Failed to generate integrity hash for bootstrap.bundle.min.js" - ) + "Failed to generate integrity hash for {} - cancelling startup!", + filepath + ); + return Err(()); } } } - }; - js_files + } + Ok(JavaScriptFiles { + all_pages, + selected, + }) } pub async fn create_https_server( @@ -149,14 +179,18 @@ pub async fn create_https_server( error!(?e, "Failed to get jws validator"); })?; - let js_files = get_js_files(config.role); + let js_files = get_js_files(config.role)?; // set up the CSP headers // script-src 'self' // 'sha384-Zao7ExRXVZOJobzS/uMp0P1jtJz3TTqJU4nYXkdmsjpiVD+/wcwCyX7FGqRIqvIz' // 'sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM' // 'unsafe-eval'; - let js_directives = js_files - .clone() + let mut all_js_files = js_files.all_pages.clone(); + for (_, jsfile) in js_files.selected.clone() { + all_js_files.push(jsfile); + } + + let js_directives = all_js_files .into_iter() .map(|f| f.hash) .collect::>(); @@ -207,12 +241,18 @@ pub async fn create_https_server( // Create a spa router that captures everything at ui without key extraction. Router::new() - // direct users to the base app page. If a login is required, - // then views will take care of redirection. We shouldn't redir - // to login because that force clears previous sessions! + // Direct users to the base app page. If a login is required, + // then views will take care of redirection. .route("/", get(|| async { Redirect::temporary("/ui") })) .route("/manifest.webmanifest", get(manifest::manifest)) // skip_route_check - .nest("/ui", ui::spa_router()) + // user UI app is the catch-all + .nest("/ui", ui::spa_router_user_ui()) + // login flows app + .nest("/ui/login", ui::spa_router_login_flows()) + .nest("/ui/reauth", ui::spa_router_login_flows()) + .nest("/ui/oauth2", ui::spa_router_login_flows()) + // admin app + .nest("/ui/admin", ui::spa_router_admin()) .layer(middleware::compression::new()) .route("/ui/images/oauth2/:rs_name", get(oauth2::oauth2_image_get)) // skip_route_check @@ -238,7 +278,8 @@ pub async fn create_https_server( } let pkg_router = Router::new() .nest_service("/pkg", ServeDir::new(pkg_path).precompressed_br()) - .layer(middleware::compression::new()); + .layer(middleware::compression::new()) + .layer(from_fn(middleware::caching::cache_me)); app.merge(pkg_router) } }; diff --git a/server/core/src/https/oauth2.rs b/server/core/src/https/oauth2.rs index b3324e73d..33d227522 100644 --- a/server/core/src/https/oauth2.rs +++ b/server/core/src/https/oauth2.rs @@ -14,6 +14,9 @@ use http::header::{ }; use http::{HeaderMap, HeaderValue, StatusCode}; use hyper::Body; +use kanidm_proto::constants::uri::{ + OAUTH2_AUTHORISE, OAUTH2_AUTHORISE_PERMIT, OAUTH2_AUTHORISE_REJECT, +}; use kanidm_proto::constants::APPLICATION_JSON; use kanidm_proto::oauth2::{AccessTokenResponse, AuthorisationResponse, OidcDiscoveryResponse}; use kanidmd_lib::idm::oauth2::{ @@ -742,19 +745,19 @@ pub fn route_setup(state: ServerState) -> Router { // ⚠️ ⚠️ WARNING ⚠️ ⚠️ // IF YOU CHANGE THESE VALUES YOU MUST UPDATE OIDC DISCOVERY URLS .route( - "/oauth2/authorise", + OAUTH2_AUTHORISE, post(oauth2_authorise_post).get(oauth2_authorise_get), ) // ⚠️ ⚠️ WARNING ⚠️ ⚠️ // IF YOU CHANGE THESE VALUES YOU MUST UPDATE OIDC DISCOVERY URLS .route( - "/oauth2/authorise/permit", + OAUTH2_AUTHORISE_PERMIT, post(oauth2_authorise_permit_post).get(oauth2_authorise_permit_get), ) // ⚠️ ⚠️ WARNING ⚠️ ⚠️ // IF YOU CHANGE THESE VALUES YOU MUST UPDATE OIDC DISCOVERY URLS .route( - "/oauth2/authorise/reject", + OAUTH2_AUTHORISE_REJECT, post(oauth2_authorise_reject_post).get(oauth2_authorise_reject_get), ) // ⚠️ ⚠️ WARNING ⚠️ ⚠️ diff --git a/server/core/src/https/tests.rs b/server/core/src/https/tests.rs index b034bbfaf..8e237016e 100644 --- a/server/core/src/https/tests.rs +++ b/server/core/src/https/tests.rs @@ -3,21 +3,21 @@ fn test_javscriptfile() { // make sure it outputs what we think it does use crate::https::JavaScriptFile; let jsf = JavaScriptFile { - filepath: "wasmloader.js", + filepath: "wasmloader_admin.js", hash: "1234567890".to_string(), filetype: Some("module".to_string()), }; assert_eq!( jsf.as_tag(), - r#""# + r#""# ); let jsf = JavaScriptFile { - filepath: "wasmloader.js", + filepath: "wasmloader_admin.js", hash: "1234567890".to_string(), filetype: None, }; assert_eq!( jsf.as_tag(), - r#""# + r#""# ); } diff --git a/server/core/src/https/ui.rs b/server/core/src/https/ui.rs index 0ec244354..2befbd7b6 100644 --- a/server/core/src/https/ui.rs +++ b/server/core/src/https/ui.rs @@ -8,58 +8,72 @@ use http::header::CONTENT_TYPE; use super::middleware::KOpId; use super::ServerState; -pub(crate) fn spa_router() -> Router { +pub(crate) fn spa_router_user_ui() -> Router { Router::new() - .route("/", get(ui_handler)) - .fallback(ui_handler) + .route("/", get(ui_handler_user_ui)) + .fallback(ui_handler_user_ui) } -pub(crate) async fn ui_handler( +/// This handles /ui/admin and all sub-paths +pub(crate) fn spa_router_admin() -> Router { + Router::new() + .route("/", get(ui_handler_admin)) + .fallback(ui_handler_admin) +} + +/// This handles the following base paths: +/// - /ui/login +/// - /ui/reauth +/// - /ui/oauth2 +pub(crate) fn spa_router_login_flows() -> Router { + Router::new() + .route("/", get(ui_handler_login_flows)) + .fallback(ui_handler_login_flows) +} + +pub(crate) async fn ui_handler_user_ui( State(state): State, Extension(kopid): Extension, +) -> Response { + ui_handler_generic(state, kopid, "wasmloader_user.js").await +} + +pub(crate) async fn ui_handler_admin( + State(state): State, + Extension(kopid): Extension, +) -> Response { + ui_handler_generic(state, kopid, "wasmloader_admin.js").await +} + +pub(crate) async fn ui_handler_login_flows( + State(state): State, + Extension(kopid): Extension, +) -> Response { + ui_handler_generic(state, kopid, "wasmloader_login_flows.js").await +} + +pub(crate) async fn ui_handler_generic( + state: ServerState, + kopid: KOpId, + wasmloader: &str, ) -> Response { let domain_display_name = state.qe_r_ref.get_domain_display_name(kopid.eventid).await; - // this feels icky but I felt that adding a trait on Vec which generated the string was going a bit far - let jsfiles: Vec = state.js_files.into_iter().map(|j| j.as_tag()).collect(); - let jstags = jsfiles.join(" "); + // let's get the tags we want to load the javascript files + let mut jsfiles: Vec = state + .js_files + .all_pages + .into_iter() + .map(|j| j.as_tag()) + .collect(); + if let Some(jsfile) = state.js_files.selected.get(wasmloader) { + jsfiles.push(jsfile.clone().as_tag()) + }; + + let jstags = jsfiles.join("\n"); let body = format!( - r#" - - - - - - - {} - - - - - - - - - - - {} - - - -
-
- -

Kanidm is loading, please wait...

-
-
- - -"#, + include_str!("ui_html.html"), domain_display_name.as_str(), jstags, ); diff --git a/server/core/src/https/ui_html.html b/server/core/src/https/ui_html.html new file mode 100644 index 000000000..7dce531f4 --- /dev/null +++ b/server/core/src/https/ui_html.html @@ -0,0 +1,40 @@ + + + + + + + + {} + + + + + + + + + + + {} + + + +
+
+ +

Kanidm is loading, please wait...

+
+
+ + + \ No newline at end of file diff --git a/server/core/src/https/v1.rs b/server/core/src/https/v1.rs index 6f2a31846..0102f65af 100644 --- a/server/core/src/https/v1.rs +++ b/server/core/src/https/v1.rs @@ -9,6 +9,7 @@ use axum::routing::{delete, get, post, put}; use axum::{Extension, Json, Router}; use compact_jwt::Jws; use http::{HeaderMap, HeaderValue}; +use kanidm_proto::constants::uri::V1_AUTH_VALID; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -3121,7 +3122,7 @@ pub(crate) fn route_setup(state: ServerState) -> Router { // get(|| async { "TODO" }), // ) .route("/v1/auth", post(auth)) - .route("/v1/auth/valid", get(auth_valid)) + .route(V1_AUTH_VALID, get(auth_valid)) .route("/v1/logout", get(logout)) .route("/v1/reauth", post(reauth)) .with_state(state.clone()) diff --git a/server/lib-macros/Cargo.toml b/server/lib-macros/Cargo.toml index b76a5c1ca..61c3805fd 100644 --- a/server/lib-macros/Cargo.toml +++ b/server/lib-macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kanidmd_lib_macros" version = "0.1.0" -edition = "2021" +edition = { workspace = true } [lib] proc-macro = true @@ -12,4 +12,3 @@ doctest = false proc-macro2 = { workspace = true } quote = { workspace = true } syn = { workspace = true } - diff --git a/server/testkit-macros/Cargo.toml b/server/testkit-macros/Cargo.toml index d1e3e9a1d..594b41382 100644 --- a/server/testkit-macros/Cargo.toml +++ b/server/testkit-macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "testkit-macros" version = "0.1.0" -edition = "2021" +edition = { workspace = true } [lib] proc-macro = true diff --git a/server/testkit/Cargo.toml b/server/testkit/Cargo.toml index 1fd2322c5..287e122d0 100644 --- a/server/testkit/Cargo.toml +++ b/server/testkit/Cargo.toml @@ -41,7 +41,7 @@ tracing = { workspace = true, features = ["attributes"] } tokio = { workspace = true, features = ["net", "sync", "io-util", "macros"] } openssl = { workspace = true } lazy_static = { workspace = true } -petgraph = { version = "0.6.4", features = ["serde"] } +petgraph = { version = "0.6.4", features = ["serde", "serde-1"] } regex.workspace = true diff --git a/server/testkit/examples/enumerating_access.rs b/server/testkit/examples/enumerating_access.rs index bfa7d0afc..7aa290582 100644 --- a/server/testkit/examples/enumerating_access.rs +++ b/server/testkit/examples/enumerating_access.rs @@ -8,13 +8,97 @@ use std::collections::{BTreeSet, HashMap}; use kanidmd_lib::constants::entries::Attribute; use kanidmd_lib::constants::groups::{idm_builtin_admin_groups, idm_builtin_non_admin_groups}; use kanidmd_lib::prelude::{builtin_accounts, EntryInitNew}; -use petgraph::graphmap::GraphMap; +use petgraph::graphmap::{AllEdges, GraphMap, NodeTrait}; +use petgraph::Directed; +use serde::{Deserialize, Serialize}; use uuid::Uuid; +#[derive(Clone, Deserialize, Serialize)] +enum EdgeType { + MemberOf, +} +#[derive(Debug)] +enum EntryType { + Person(String), + ServiceAccount(String), + Group(String), + UnknownType(String), +} + +impl EntryType { + fn as_mermaid_tag(&self) -> String { + match self { + EntryType::Person(name) => format!("{}(\"Person:{}\")", name, name), + EntryType::ServiceAccount(name) => format!("{}{{\"SA: {}\"}}", name, name), + EntryType::Group(name) => format!("{}[\"Group: {}\"]", name, name), + EntryType::UnknownType(name) => format!("{}[\"Unknown Type {}\"]", name, name), + } + } +} + +impl From<&EntryInitNew> for EntryType { + fn from(entry: &EntryInitNew) -> Self { + let name = entry.get_ava_single(Attribute::Name).unwrap(); + let name = name.as_string().unwrap(); + let classes = entry + .get_ava_set(Attribute::Class) + .unwrap() + .as_iutf8_set() + .cloned() + .unwrap_or(BTreeSet::::new()); + if classes.contains("group") { + EntryType::Group(name.clone()) + } else if classes.contains("service_account") { + EntryType::ServiceAccount(name.clone()) + } else if classes.contains("person") { + EntryType::Person(name.clone()) + } else { + EntryType::UnknownType(name.clone()) + } + } +} + +struct Graph(GraphMap); + +impl Graph +where + T: core::hash::Hash + Ord + NodeTrait, +{ + fn new() -> Self { + Graph(GraphMap::::new()) + } + + fn add_node(&mut self, n: T) { + self.0.add_node(n); + } + fn add_edge(&mut self, l: T, r: T, t: EdgeType) { + self.0.add_edge(l, r, t); + } + fn all_edges(&mut self) -> AllEdges<'_, T, EdgeType, Directed> { + self.0.all_edges() + } + + /// The uuidmap is a map of uuids to EntryInitNew objects, which we use to get the name of the objects + fn as_mermaid(&mut self, uuidmap: &HashMap) -> String { + let mut res = format!("graph RL;\n"); + for (left, right, _weight) in self.all_edges() { + let left = uuidmap.get(&left).unwrap(); + let right = uuidmap.get(&right).unwrap(); + + res += &format!( + " {} --> {}\n", + EntryType::from(left).as_mermaid_tag(), + EntryType::from(right).as_mermaid_tag(), + ); + } + res + } +} + async fn enumerate_default_groups(/*_client: KanidmClient*/) { let mut uuidmap: HashMap = HashMap::new(); - let mut graph = GraphMap::::new(); + let mut graph = Graph::new(); builtin_accounts().into_iter().for_each(|account| { // println!("adding builtin {}", account.uuid); @@ -22,95 +106,20 @@ async fn enumerate_default_groups(/*_client: KanidmClient*/) { graph.add_node(account.uuid); }); - idm_builtin_non_admin_groups() - .into_iter() - .for_each(|group| { - uuidmap.insert(group.uuid, group.clone().try_into().unwrap()); - graph.add_node(group.uuid); + let mut groups = idm_builtin_admin_groups(); + groups.extend(idm_builtin_non_admin_groups()); - group.members.iter().for_each(|member| { - graph.add_edge(*member, group.uuid, ()); - }); - }); - - idm_builtin_admin_groups().into_iter().for_each(|group| { + groups.into_iter().for_each(|group| { uuidmap.insert(group.uuid, group.clone().try_into().unwrap()); graph.add_node(group.uuid); + // handle the membership group.members.iter().for_each(|member| { - graph.add_edge(*member, group.uuid, ()); + graph.add_edge(*member, group.uuid, EdgeType::MemberOf); }); }); - // // println!("{}", mermaidchart); - // let mut dotgraph = format!("{:?}", Dot::with_config(&graph, &[Config::EdgeNoLabel])); - // // regex to extract uuids - // // let re = regex::Regex::new(r"(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})").unwrap(); - // for (uuid, uuid_value) in uuidmap.clone() { - // let uuid_str = uuid.to_string(); - // if dotgraph.contains(&uuid_str) { - // // println!("uuid {} not found in graph", uuid_str); - // let name = uuid_value.get_ava_single(Attribute::Name).unwrap(); - // dotgraph = dotgraph.replace(&uuid_str, name.as_string().unwrap()); - // } - // } - // // println!("{}", dotgraph); - - #[derive(Debug)] - enum EntryType { - Person(String), - ServiceAccount(String), - Group(String), - UnknownType(String), - } - - impl EntryType { - fn as_mermaid_tag(&self) -> String { - match self { - EntryType::Person(name) => format!("{}(\"Person:{}\")", name, name), - EntryType::ServiceAccount(name) => format!("{}{{\"SA: {}\"}}", name, name), - EntryType::Group(name) => format!("{}[\"Group: {}\"]", name, name), - EntryType::UnknownType(name) => format!("{}[\"Unknown Type {}\"]", name, name), - } - } - } - - impl From for EntryType { - fn from(entry: EntryInitNew) -> Self { - let name = entry.get_ava_single(Attribute::Name).unwrap(); - let name = name.as_string().unwrap(); - let classes = entry - .get_ava_set(Attribute::Class) - .unwrap() - .as_iutf8_set() - .cloned() - .unwrap_or(BTreeSet::::new()); - if classes.contains("group") { - EntryType::Group(name.clone()) - } else if classes.contains("service_account") { - EntryType::ServiceAccount(name.clone()) - } else if classes.contains("person") { - EntryType::Person(name.clone()) - } else { - EntryType::UnknownType(name.clone()) - } - } - } - - println!("graph RL;"); - for (left, right, _weight) in graph.all_edges() { - let left = uuidmap.get(&left).unwrap(); - // let left_name = left.get_ava_single(Attribute::Name).unwrap(); - - let right = uuidmap.get(&right).unwrap(); - // let right_name = right.get_ava_single(Attribute::Name).unwrap(); - - println!( - " {} --> {}", - EntryType::from(left.clone()).as_mermaid_tag(), - EntryType::from(right.clone()).as_mermaid_tag(), - ); - } + println!("{}", graph.as_mermaid(&uuidmap)) } #[tokio::main] diff --git a/server/testkit/tests/oauth2_test.rs b/server/testkit/tests/oauth2_test.rs index a67410529..cef169ce1 100644 --- a/server/testkit/tests/oauth2_test.rs +++ b/server/testkit/tests/oauth2_test.rs @@ -4,6 +4,7 @@ use std::convert::TryFrom; use std::str::FromStr; use compact_jwt::{JwkKeySet, JwsValidator, OidcToken, OidcUnverified}; +use kanidm_proto::constants::uri::{OAUTH2_AUTHORISE, OAUTH2_AUTHORISE_PERMIT}; use kanidm_proto::constants::*; use kanidm_proto::oauth2::{ AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, @@ -221,7 +222,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) { let (pkce_code_challenge, pkce_code_verifier) = PkceCodeChallenge::new_random_sha256(); let response = client - .get(rsclient.make_url("/oauth2/authorise")) + .get(rsclient.make_url(OAUTH2_AUTHORISE)) .bearer_auth(oauth_test_uat.clone()) .query(&[ ("response_type", "code"), @@ -261,7 +262,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) { // state and code. let response = client - .get(rsclient.make_url("/oauth2/authorise/permit")) + .get(rsclient.make_url(OAUTH2_AUTHORISE_PERMIT)) .bearer_auth(oauth_test_uat) .query(&[("token", consent_token.as_str())]) .send() @@ -521,7 +522,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) { let (pkce_code_challenge, pkce_code_verifier) = PkceCodeChallenge::new_random_sha256(); let response = client - .get(rsclient.make_url("/oauth2/authorise")) + .get(rsclient.make_url(OAUTH2_AUTHORISE)) .bearer_auth(oauth_test_uat.clone()) .query(&[ ("response_type", "code"), @@ -560,7 +561,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) { // Step 2 - we now send the consent get to the server which yields a redirect with a // state and code. let response = client - .get(rsclient.make_url("/oauth2/authorise/permit")) + .get(rsclient.make_url(OAUTH2_AUTHORISE_PERMIT)) .bearer_auth(oauth_test_uat) .query(&[("token", consent_token.as_str())]) .send() diff --git a/server/web_ui/admin/Cargo.toml b/server/web_ui/admin/Cargo.toml new file mode 100644 index 000000000..49c546dfd --- /dev/null +++ b/server/web_ui/admin/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "kanidmd_web_ui_admin" +description = "Kanidm Server Web UI - Admin Interface" +documentation = "https://docs.rs/kanidm/latest/kanidm/" + +version = { workspace = true } +authors = [ + "William Brown ", + "James Hodgkinson ", +] +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +kanidm_proto = { workspace = true, features = ["wasm"] } +kanidmd_web_ui_shared = { workspace = true } +gloo = { workspace = true } +js-sys = { workspace = true } +lazy_static.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde-wasm-bindgen = { workspace = true } +time = { workspace = true } +url = { workspace = true } +uuid = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +yew = { workspace = true, features = ["csr"] } +yew-router = { workspace = true } +gloo-utils = { workspace = true } + +[dependencies.web-sys] +workspace = true +features = [ + # "AuthenticationExtensionsClientOutputs", + # "AuthenticatorResponse", + # "CredentialCreationOptions", + # "CredentialRequestOptions", + # "CredentialsContainer", + "DomTokenList", + "Element", + "Event", + "FocusEvent", + "FormData", + "Headers", + "HtmlButtonElement", + "HtmlDocument", + "HtmlFormElement", + "Navigator", + # "PublicKeyCredential", + # "PublicKeyCredentialCreationOptions", + # "PublicKeyCredentialRpEntity", + # "PublicKeyCredentialUserEntity", + "Request", + # "RequestCredentials", + # "RequestInit", + # "RequestMode", + # "RequestRedirect", + "Response", + "Window", +] + +[dev-dependencies] +wasm-bindgen-test = { workspace = true } diff --git a/server/web_ui/admin/build_dev.sh b/server/web_ui/admin/build_dev.sh new file mode 100755 index 000000000..e3f10e598 --- /dev/null +++ b/server/web_ui/admin/build_dev.sh @@ -0,0 +1,2 @@ +#!/bin/sh +BUILD_FLAGS="--dev" ./build.sh diff --git a/server/web_ui/README.md b/server/web_ui/admin/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC similarity index 100% rename from server/web_ui/README.md rename to server/web_ui/admin/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC diff --git a/server/web_ui/admin/pkg/kanidmd_web_ui_admin.js b/server/web_ui/admin/pkg/kanidmd_web_ui_admin.js new file mode 100644 index 000000000..948448548 --- /dev/null +++ b/server/web_ui/admin/pkg/kanidmd_web_ui_admin.js @@ -0,0 +1,1033 @@ +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} + +let stack_pointer = 128; + +function addBorrowedObject(obj) { + if (stack_pointer == 1) throw new Error('out of js stack'); + heap[--stack_pointer] = obj; + return stack_pointer; +} +function __wbg_adapter_38(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h978a6dc8b85306b0(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +function __wbg_adapter_41(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h5882a5a28fa681a9(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_44(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd935f1f8cef6ff5a(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +/** +* This is the entry point of the web front end. This triggers the manager app to load and begin +* its event loop. +*/ +export function run_app() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.run_app(retptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +let cachedUint32Memory0 = null; + +function getUint32Memory0() { + if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) { + cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32Memory0; +} + +function getArrayJsValueFromWasm0(ptr, len) { + ptr = ptr >>> 0; + const mem = getUint32Memory0(); + const slice = mem.subarray(ptr / 4, ptr / 4 + len); + const result = []; + for (let i = 0; i < slice.length; i++) { + result.push(takeObject(slice[i])); + } + return result; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbindgen_in = function(arg0, arg1) { + const ret = getObject(arg0) in getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { + const ret = getObject(arg0) == getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_number_new = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setlistenerid_3183aae8fa5840fb = function(arg0, arg1) { + getObject(arg0).__yew_listener_id = arg1 >>> 0; + }; + imports.wbg.__wbg_listenerid_12315eee21527820 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_listener_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_subtreeid_e348577f7ef777e3 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setsubtreeid_d32e6327eef1f7fc = function(arg0, arg1) { + getObject(arg0).__yew_subtree_id = arg1 >>> 0; + }; + imports.wbg.__wbg_cachekey_b61393159c57fd7b = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_cache_key; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setcachekey_80183b7cfc421143 = function(arg0, arg1) { + getObject(arg0).__yew_subtree_cache_key = arg1 >>> 0; + }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_getwithrefkey_5e6d9547403deab8 = function(arg0, arg1) { + const ret = getObject(arg0)[getObject(arg1)]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_841ac57cff3d672b = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_debug_783a3d4910bc24c7 = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.debug(...v0); + }; + imports.wbg.__wbg_error_71d6845bf00a930f = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.error(...v0); + }; + imports.wbg.__wbg_log_1f7f93998ab961f7 = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.log(...v0); + }; + imports.wbg.__wbg_body_674aec4c1c0910cd = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createElementNS_119acf9e82482041 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createTextNode_2fd22cd7e543f938 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_querySelector_52ded52c20e23921 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).querySelector(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Element; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_namespaceURI_31718ed49b5343a3 = function(arg0, arg1) { + const ret = getObject(arg1).namespaceURI; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_classList_5f2fc1d67656292e = function(arg0) { + const ret = getObject(arg0).classList; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setinnerHTML_b089587252408b67 = function(arg0, arg1, arg2) { + getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_outerHTML_f7749ceff37b5832 = function(arg0, arg1) { + const ret = getObject(arg1).outerHTML; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_children_27ed308801b57d3f = function(arg0) { + const ret = getObject(arg0).children; + return addHeapObject(ret); + }; + imports.wbg.__wbg_removeAttribute_d8404da431968808 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setAttribute_e7e80b478b7b8b2f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_location_56243dba507f472d = function(arg0) { + const ret = getObject(arg0).location; + return addHeapObject(ret); + }; + imports.wbg.__wbg_history_3c2280e6b2a9316e = function() { return handleError(function (arg0) { + const ret = getObject(arg0).history; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_localStorage_dbac11bd189e9fa0 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).localStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_sessionStorage_3b863b6e15dd2bdc = function() { return handleError(function (arg0) { + const ret = getObject(arg0).sessionStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_fetch_336b6f0cb426b46e = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_add_3eafedc4b2a28db0 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).add(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_get_2e9aab260014946d = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).get(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_set_b34caba58723c454 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_state_745dc4814d321eb3 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).state; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_pushState_1145414a47c0b629 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).pushState(getObject(arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); + }, arguments) }; + imports.wbg.__wbg_headers_b439dcff02e808e5 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithstrandinit_cad5cd6038c7ff5d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_status_ac85a3142a84caa2 = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_headers_b70de86b8e989bc0 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_json_2a46ed5b7c4d30d1 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).json(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_ShadowRoot_b64337370f59fe2d = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ShadowRoot; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_host_e1c47c33975060d3 = function(arg0) { + const ret = getObject(arg0).host; + return addHeapObject(ret); + }; + imports.wbg.__wbg_href_17ed54b321396524 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_pathname_57290e07c6bc0683 = function(arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_search_2ff3bb9114e0ca34 = function(arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setsearch_16b87f04ea0e6b80 = function(arg0, arg1, arg2) { + getObject(arg0).search = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_hash_2b57e787945b2db0 = function(arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_sethash_41d6e65816639c62 = function(arg0, arg1, arg2) { + getObject(arg0).hash = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_new_a76f6bcb38f791ea = function() { return handleError(function (arg0, arg1) { + const ret = new URL(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_newwithbase_79b8cac27ce631ac = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = new URL(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_href_d62a28e4fc1ab948 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_sethref_e5626365d7354fea = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).href = getStringFromWasm0(arg1, arg2); + }, arguments) }; + imports.wbg.__wbg_pathname_c8fd5c498079312d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_search_6c3c472e076ee010 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_hash_a1a795b89dda8e3d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_bubbles_63572b91f3885ef1 = function(arg0) { + const ret = getObject(arg0).bubbles; + return ret; + }; + imports.wbg.__wbg_cancelBubble_90d1c3aa2a76cbeb = function(arg0) { + const ret = getObject(arg0).cancelBubble; + return ret; + }; + imports.wbg.__wbg_composedPath_cf1bb5b8bcff496f = function(arg0) { + const ret = getObject(arg0).composedPath(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbg_href_47b90f0ddf3ddcd7 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_addEventListener_a5963e26cd7b176b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbg_removeEventListener_782040b4432709cb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); + }, arguments) }; + imports.wbg.__wbg_parentNode_9e53f8b17eb98c9d = function(arg0) { + const ret = getObject(arg0).parentNode; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_parentElement_c75962bc9997ea5f = function(arg0) { + const ret = getObject(arg0).parentElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_lastChild_0cee692010bac6c2 = function(arg0) { + const ret = getObject(arg0).lastChild; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_nextSibling_304d9aac7c2774ae = function(arg0) { + const ret = getObject(arg0).nextSibling; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_setnodeValue_d1c8382910b45e04 = function(arg0, arg1, arg2) { + getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_textContent_c5d9e21ee03c63d4 = function(arg0, arg1) { + const ret = getObject(arg1).textContent; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_appendChild_51339d4cde00ee22 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_insertBefore_ffa01d4b747c95fc = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_removeChild_973429f368206138 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).removeChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_setchecked_e5a50baea447b8a8 = function(arg0, arg1) { + getObject(arg0).checked = arg1 !== 0; + }; + imports.wbg.__wbg_value_9423da9d988ee8cf = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_1f95e61cbc382f7f = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_value_3c5f08ffc2b7d6f9 = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_0dc100d4b9908028 = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_getItem_ed8e218e51f1efeb = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_removeItem_02359267b311cb85 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeItem(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setItem_d002ee486462bfff = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) { + const ret = getObject(arg0).next; + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) { + const ret = getObject(arg0).next(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() { + const ret = Symbol.iterator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_from_d7c216d4616bb368 = function(arg0) { + const ret = Array.from(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function(arg0) { + const ret = Array.isArray(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_Error_ab19e20608ea43c7 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Error; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_message_48bacc5ea57d74ee = function(arg0) { + const ret = getObject(arg0).message; + return addHeapObject(ret); + }; + imports.wbg.__wbg_name_8f734cbbd6194153 = function(arg0) { + const ret = getObject(arg0).name; + return addHeapObject(ret); + }; + imports.wbg.__wbg_toString_1c056108b87ba68b = function(arg0) { + const ret = getObject(arg0).toString(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isSafeInteger_bb8e18dd21c97288 = function(arg0) { + const ret = Number.isSafeInteger(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_entries_e51f29c7bba0c054 = function(arg0) { + const ret = Object.entries(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_is_205d914af04a8faa = function(arg0, arg1) { + const ret = Object.is(getObject(arg0), getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_f7e06ee3c11698eb = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_b2267541e2a73865 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Uint8Array; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1254 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 572, __wbg_adapter_38); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1368 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 625, __wbg_adapter_41); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1448 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 660, __wbg_adapter_44); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('kanidmd_web_ui_admin_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/server/web_ui/admin/pkg/kanidmd_web_ui_admin_bg.wasm b/server/web_ui/admin/pkg/kanidmd_web_ui_admin_bg.wasm new file mode 100644 index 000000000..3d041fe28 Binary files /dev/null and b/server/web_ui/admin/pkg/kanidmd_web_ui_admin_bg.wasm differ diff --git a/server/web_ui/admin/pkg/wasmloader_admin.js b/server/web_ui/admin/pkg/wasmloader_admin.js new file mode 100644 index 000000000..8fab05c0e --- /dev/null +++ b/server/web_ui/admin/pkg/wasmloader_admin.js @@ -0,0 +1,7 @@ +// loads the module which loads the WASM. It's loaders all the way down. +import init, { run_app } from '/pkg/kanidmd_web_ui_admin.js'; +async function main() { + await init('/pkg/kanidmd_web_ui_admin_bg.wasm'); + run_app(); +} +main() diff --git a/server/web_ui/src/components/admin_accounts.rs b/server/web_ui/admin/src/components/admin_accounts.rs similarity index 93% rename from server/web_ui/src/components/admin_accounts.rs rename to server/web_ui/admin/src/components/admin_accounts.rs index 209dd0a1d..35135d79b 100644 --- a/server/web_ui/src/components/admin_accounts.rs +++ b/server/web_ui/admin/src/components/admin_accounts.rs @@ -4,14 +4,10 @@ use gloo::console; use yew::{html, Component, Context, Html, Properties}; use yew_router::prelude::Link; +use super::prelude::*; use crate::components::admin_menu::{Entity, EntityType, GetError}; -use crate::components::alpha_warning_banner; -use crate::constants::{ - CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE, CSS_CELL, CSS_DT, CSS_TABLE, -}; -use crate::utils::{do_alert_error, do_page_header}; -use crate::views::AdminRoute; -use crate::{do_request, RequestMethod}; +use crate::router::AdminRoute; +use kanidmd_web_ui_shared::constants::{CSS_CELL, CSS_DT, CSS_TABLE}; impl From for AdminListAccountsMsg { fn from(ge: GetError) -> Self { @@ -185,11 +181,6 @@ impl Component for AdminListAccounts { fn view(&self, _ctx: &Context) -> Html { html! { <> - - {do_page_header("Account Administration")} { alpha_warning_banner() }
@@ -269,12 +260,12 @@ impl Component for AdminListAccounts { console::error!("Failed to pull details", format!("{:?}", kopid)); html!( <> - {do_alert_error("Failed to Query Accounts", Some(emsg))} + {do_alert_error("Failed to Query Accounts", Some(emsg), false)} ) } ViewState::NotAuthorized {} => { - do_alert_error("You're not authorized to see this page!", None) + do_alert_error("You're not authorized to see this page!", None, false) } }}
@@ -353,6 +344,7 @@ impl Component for AdminViewPerson { ViewAccountState::Failed { emsg, kopid } => do_alert_error( emsg.clone().as_str(), Some(&format!("Operation ID: {:?}", kopid)), + false, ), // TODO: the not authorized page needs to be better ViewAccountState::NotAuthorized {} => { @@ -381,11 +373,6 @@ impl Component for AdminViewPerson { // }; html! { <> - {do_page_header(display_name.as_str())} {alpha_warning_banner()} @@ -504,11 +491,7 @@ impl Component for AdminViewServiceAccount { html! { <> - + {do_page_header(&format!("Service Account: {}", username))} {alpha_warning_banner()}

{"Display Name: "}{displayname}

@@ -517,7 +500,7 @@ impl Component for AdminViewServiceAccount { } } ViewAccountState::Failed { emsg, kopid } => html! { - do_alert_error(emsg.as_str(), Some(&format!("Operation ID: {:?}", kopid))) + do_alert_error(emsg.as_str(), Some(&format!("Operation ID: {:?}", kopid)), false) }, // TODO: this error needs fixing ViewAccountState::NotAuthorized {} => { diff --git a/server/web_ui/src/components/admin_groups.rs b/server/web_ui/admin/src/components/admin_groups.rs similarity index 94% rename from server/web_ui/src/components/admin_groups.rs rename to server/web_ui/admin/src/components/admin_groups.rs index ef2fa4f52..a7907fe49 100644 --- a/server/web_ui/src/components/admin_groups.rs +++ b/server/web_ui/admin/src/components/admin_groups.rs @@ -1,15 +1,14 @@ use std::collections::BTreeMap; use gloo::console; +use kanidmd_web_ui_shared::utils::{do_alert_error, do_page_header}; use yew::{html, Component, Context, Html, Properties}; use yew_router::prelude::Link; use crate::components::admin_menu::{Entity, EntityType, GetError}; -use crate::components::alpha_warning_banner; -use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE, CSS_CELL, CSS_TABLE}; -use crate::utils::{do_alert_error, do_page_header}; -use crate::views::AdminRoute; -use crate::{do_request, RequestMethod}; +use crate::router::AdminRoute; +use kanidmd_web_ui_shared::constants::{CSS_CELL, CSS_TABLE}; +use kanidmd_web_ui_shared::{alpha_warning_banner, do_request, RequestMethod}; impl From for AdminListGroupsMsg { fn from(ge: GetError) -> Self { @@ -224,12 +223,12 @@ impl AdminListGroups { console::error!("Failed to pull details", format!("{:?}", kopid)); html!( <> - {do_alert_error("Failed to Query Groups", Some(emsg))} + {do_alert_error("Failed to Query Groups", Some(emsg), false)} ) } GroupsViewState::NotAuthorized {} => { - do_alert_error("You're not authorized to see this page!", None) + do_alert_error("You're not authorized to see this page!", None, false) } } } @@ -318,11 +317,6 @@ impl Component for AdminViewGroup { }; html! { <> - {do_page_header(&page_title)}

{"UUID: "}{group_uuid}

// TODO: pull group membership and show members @@ -337,9 +331,10 @@ impl Component for AdminViewGroup { .as_ref() .unwrap_or(&String::from("unknown operation ID")), ), + false, ), GroupViewState::NotAuthorized {} => { - do_alert_error("You are not authorized to view this page!", None) + do_alert_error("You are not authorized to view this page!", None, false) } } } diff --git a/server/web_ui/src/components/admin_menu.rs b/server/web_ui/admin/src/components/admin_menu.rs similarity index 95% rename from server/web_ui/src/components/admin_menu.rs rename to server/web_ui/admin/src/components/admin_menu.rs index c79b40533..82a9b49d3 100644 --- a/server/web_ui/src/components/admin_menu.rs +++ b/server/web_ui/admin/src/components/admin_menu.rs @@ -1,11 +1,13 @@ +use kanidmd_web_ui_shared::alpha_warning_banner; use serde::{Deserialize, Serialize}; use yew::{html, Component, Context, Html, Properties}; use yew_router::prelude::Link; -use crate::components::alpha_warning_banner; -use crate::constants::{CSS_CARD, CSS_CARD_BODY, CSS_LINK_DARK_STRETCHED, CSS_PAGE_HEADER}; +use kanidmd_web_ui_shared::constants::{ + CSS_CARD, CSS_CARD_BODY, CSS_LINK_DARK_STRETCHED, CSS_PAGE_HEADER, +}; // use crate::error::FetchError; -use crate::views::AdminRoute; +use crate::router::AdminRoute; #[derive(Eq, PartialEq, Properties)] pub struct Props; diff --git a/server/web_ui/src/components/admin_oauth2.rs b/server/web_ui/admin/src/components/admin_oauth2.rs similarity index 93% rename from server/web_ui/src/components/admin_oauth2.rs rename to server/web_ui/admin/src/components/admin_oauth2.rs index 4e65369f2..1aa183494 100644 --- a/server/web_ui/src/components/admin_oauth2.rs +++ b/server/web_ui/admin/src/components/admin_oauth2.rs @@ -4,12 +4,10 @@ use gloo::console; use yew::{html, Component, Context, Html, Properties}; use yew_router::prelude::Link; +use super::prelude::*; use crate::components::admin_menu::{Entity, EntityType, GetError}; -use crate::components::alpha_warning_banner; -use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE, CSS_CELL, CSS_TABLE}; -use crate::utils::{do_alert_error, do_page_header}; -use crate::views::AdminRoute; -use crate::{do_request, RequestMethod}; +use crate::router::AdminRoute; +use kanidmd_web_ui_shared::constants::{CSS_CELL, CSS_TABLE}; impl From for AdminListOAuth2Msg { fn from(ge: GetError) -> Self { @@ -164,10 +162,6 @@ impl Component for AdminListOAuth2 { html! { <> - {do_page_header("OAuth2")} { alpha_warning_banner() } @@ -237,12 +231,12 @@ impl Component for AdminListOAuth2 { console::error!("Failed to pull details", format!("{:?}", kopid)); html!( <> - {do_alert_error("Failed to Query OAuth2", Some(emsg))} + {do_alert_error("Failed to Query OAuth2", Some(emsg), false)} ) } ListViewState::NotAuthorized {} => { - do_alert_error("You're not authorized to see this page!", None) + do_alert_error("You're not authorized to see this page!", None, false) } } } @@ -350,11 +344,6 @@ impl Component for AdminViewOAuth2 { html! { <> - {do_page_header(display_name.as_str())} {alpha_warning_banner()} @@ -369,12 +358,12 @@ impl Component for AdminViewOAuth2 { console::error!("Failed to pull details", format!("{:?}", kopid)); html!( <> - {do_alert_error("Failed to Query OAuth2", Some(emsg))} + {do_alert_error("Failed to Query OAuth2", Some(emsg), false)} ) } ViewState::NotAuthorized {} => { - do_alert_error("You're not authorized to see this page!", None) + do_alert_error("You're not authorized to see this page!", None, false) } } } diff --git a/server/web_ui/admin/src/components/mod.rs b/server/web_ui/admin/src/components/mod.rs new file mode 100644 index 000000000..a13d30635 --- /dev/null +++ b/server/web_ui/admin/src/components/mod.rs @@ -0,0 +1,11 @@ +pub mod admin_accounts; +pub mod admin_groups; +pub mod admin_menu; +pub mod admin_oauth2; + +mod prelude { + + pub use kanidmd_web_ui_shared::alpha_warning_banner; + pub use kanidmd_web_ui_shared::utils::{do_alert_error, do_page_header}; + pub use kanidmd_web_ui_shared::{do_request, RequestMethod}; +} diff --git a/server/web_ui/admin/src/lib.rs b/server/web_ui/admin/src/lib.rs new file mode 100644 index 000000000..ba5e3a31e --- /dev/null +++ b/server/web_ui/admin/src/lib.rs @@ -0,0 +1,152 @@ +mod components; +mod router; + +use gloo::console::{self, error}; +use kanidmd_web_ui_shared::add_body_form_classes; +use kanidmd_web_ui_shared::constants::{ + CSS_NAVBAR_BRAND, CSS_NAVBAR_LINKS_UL, CSS_NAVBAR_NAV, CSS_NAV_LINK, ID_NAVBAR_COLLAPSE, + IMG_LOGO_SQUARE, URL_USER_HOME, +}; +use kanidmd_web_ui_shared::ui::{signout_link, signout_modal, ui_logout}; +use kanidmd_web_ui_shared::utils::do_footer; +#[allow(unused_imports)] // because it's needed to compile wasm things +use wasm_bindgen::prelude::wasm_bindgen; +use wasm_bindgen::JsValue; + +use yew::{html, Component, Context, Html}; +use yew_router::prelude::Link; +use yew_router::{BrowserRouter, Switch}; + +use crate::router::AdminRoute; + +pub struct AdminApp {} + +/// This builds the navbar, it's not generic because the link on the logo is different +fn make_navbar(links: Vec) -> Html { + html! { + + } +} + +#[derive(Clone, Debug)] +pub enum AdminViewsMsg { + Logout, + LogoutComplete, +} + +impl Component for AdminApp { + type Message = AdminViewsMsg; + type Properties = (); + + fn create(_ctx: &Context) -> Self { + #[cfg(debug_assertions)] + console::debug!("manager::create"); + AdminApp {} + } + + fn changed(&mut self, _ctx: &Context, _props: &Self::Properties) -> bool { + #[cfg(debug_assertions)] + console::debug!("manager::change"); + false + } + + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { + #[cfg(debug_assertions)] + console::debug!("manager::update"); + match msg { + AdminViewsMsg::Logout => { + console::debug!("manager::update -> logout"); + + ctx.link().send_future(async { + match Self::fetch_logout().await { + Ok(v) => v, + Err(v) => { + error!("... failed to log out? {:?}", v); + AdminViewsMsg::Logout + } + } + }); + } + AdminViewsMsg::LogoutComplete => { + let window = gloo_utils::window(); + window.location().set_href(URL_USER_HOME).unwrap(); + } + } + + true + } + + fn rendered(&mut self, _ctx: &Context, _first_render: bool) { + #[cfg(debug_assertions)] + console::debug!("manager::rendered"); + } + + fn view(&self, ctx: &Context) -> Html { + add_body_form_classes!(); + + let links = vec![ + html! {{"Home"}}, + html! { classes={CSS_NAV_LINK} to={AdminRoute::AdminMenu}>{"Admin"}>}, + html! { classes={CSS_NAV_LINK} to={AdminRoute::AdminListAccounts}>{"Accounts"}>}, + html! { classes={CSS_NAV_LINK} to={AdminRoute::AdminListGroups}>{"Groups"}>}, + html! { classes={CSS_NAV_LINK} to={AdminRoute::AdminListOAuth2}>{"OAuth2"}>}, + signout_link(), + ]; + + html! { + + + // sign out modal dialogue box + {signout_modal(ctx, AdminViewsMsg::Logout)} + {make_navbar(links)} + +
+ render={ router::switch } /> +
+ { do_footer() } +
+ } + } +} + +impl AdminApp { + async fn fetch_logout() -> Result { + match ui_logout().await { + Ok(_) => Ok(AdminViewsMsg::LogoutComplete), + Err((emsg, _kopid)) => { + error!("failed to process logout request: {}", emsg); + Ok(AdminViewsMsg::Logout) + } + } + } +} + +/// This is the entry point of the web front end. This triggers the manager app to load and begin +/// its event loop. +#[cfg_attr(target_arch = "wasm32", wasm_bindgen)] +pub fn run_app() -> Result<(), JsValue> { + yew::Renderer::::new().render(); + Ok(()) +} diff --git a/server/web_ui/admin/src/router.rs b/server/web_ui/admin/src/router.rs new file mode 100644 index 000000000..d3b68be54 --- /dev/null +++ b/server/web_ui/admin/src/router.rs @@ -0,0 +1,68 @@ +#![allow(clippy::disallowed_types)] // because `Routable` uses a hashmap + +use serde::{Deserialize, Serialize}; +use yew::{html, Html}; +use yew_router::prelude::Redirect; +use yew_router::Routable; + +use crate::components; + +#[derive(Routable, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] +pub enum AdminRoute { + #[at("/ui/admin")] + AdminMenu, + #[at("/ui/admin/groups")] + AdminListGroups, + #[at("/ui/admin/accounts")] + AdminListAccounts, + #[at("/ui/admin/oauth2")] + AdminListOAuth2, + + #[at("/ui/admin/group/:uuid")] + ViewGroup { uuid: String }, + #[at("/ui/admin/person/:uuid")] + ViewPerson { uuid: String }, + #[at("/ui/admin/service_account/:uuid")] + ViewServiceAccount { uuid: String }, + #[at("/ui/admin/oauth2/:rs_name")] + ViewOAuth2RP { rs_name: String }, + + #[not_found] + #[at("/ui/admin/404")] + NotFound, +} + +pub(crate) fn switch(route: AdminRoute) -> Html { + match route { + AdminRoute::AdminMenu => html! { + + }, + AdminRoute::AdminListAccounts => html!( + + ), + AdminRoute::AdminListGroups => html!( + + ), + AdminRoute::AdminListOAuth2 => html!( + + ), + AdminRoute::ViewGroup { uuid } => { + html!() + // html! {<>} + } + AdminRoute::ViewPerson { uuid } => html!( + + ), + AdminRoute::ViewServiceAccount { uuid } => html!( + + // html! {<>} + ), + AdminRoute::ViewOAuth2RP { rs_name } => html! { + + + }, + AdminRoute::NotFound => html! ( + to={AdminRoute::NotFound}/> + ), + } +} diff --git a/server/web_ui/admin/static/wasmloader_admin.js b/server/web_ui/admin/static/wasmloader_admin.js new file mode 100644 index 000000000..8fab05c0e --- /dev/null +++ b/server/web_ui/admin/static/wasmloader_admin.js @@ -0,0 +1,7 @@ +// loads the module which loads the WASM. It's loaders all the way down. +import init, { run_app } from '/pkg/kanidmd_web_ui_admin.js'; +async function main() { + await init('/pkg/kanidmd_web_ui_admin_bg.wasm'); + run_app(); +} +main() diff --git a/server/web_ui/build_wasm.sh b/server/web_ui/build_wasm.sh index 0e2c75d3a..1ac0cc0a5 100755 --- a/server/web_ui/build_wasm.sh +++ b/server/web_ui/build_wasm.sh @@ -1,44 +1,66 @@ #!/bin/sh set -e -# This builds the assets for the Web UI, defaulting to a release build. +# This builds the assets for the Web UI, defaulting to a release build. if [ ! -f build_wasm.sh ]; then echo "Please run from the crate directory. (server/web_ui)" exit 1 fi - -if [ -z "${BUILD_FLAGS}" ]; then - BUILD_FLAGS="--release --no-typescript" -fi - if [ -z "$(which rsync)" ]; then echo "Cannot find rsync which is needed to move things around, quitting!" exit 1 fi - if [ -z "$(which wasm-pack)" ]; then echo "Cannot find wasm-pack which is needed to build the UI, quitting!" exit 1 fi -if [ "$(find ./pkg/ -name 'kanidmd*' | wc -l)" -gt 0 ]; then - echo "Cleaning up WASM files before build..." - rm pkg/kanidmd* +if [ -z "${BUILD_FLAGS}" ]; then + export BUILD_FLAGS="--release" fi -# we can disable this since we want it to expand -# shellcheck disable=SC2086 -wasm-pack build ${BUILD_FLAGS} --target web --mode no-install --no-pack +echo "Cleaning up pkg dir" +find pkg/ -type f -delete +find pkg/ -mindepth 1 -type d -delete -touch ./pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC && \ - rsync --delete-after -r --copy-links -v ./static/* ./pkg/ && \ - cp ../../README.md ./pkg/ - cp ../../LICENSE.md ./pkg/ +touch ./pkg/ANYTHING_HERE_WILL_BE_DELETED_IN_BUILDS +# cp ../../README.md ./pkg/ +# cp ../../LICENSE.md ./pkg/ +if [ -f ./pkg/.gitignore ]; then rm ./pkg/.gitignore +fi + +# copy the shared static things +rsync -av shared/static/* shared/static/* pkg/ + + +cd admin +echo "building admin" +../individual_build.sh || exit 1 +cd .. +echo "done building admin" + +cd login_flows +echo "building login_flows" +../individual_build.sh || exit 1 +cd .. +echo "done building login_flows" + +cd user +echo "building user" +../individual_build.sh || exit 1 +cd .. +echo "done building user" + + if [ -z "${SKIP_BROTLI}" ]; then # updates the brotli-compressed files - echo "brotli-compressing the WASM file..." - find ./pkg -name '*.wasm' -exec ./find_best_brotli.sh "{}" \; || exit 1 -fi \ No newline at end of file + echo "brotli-compressing compressible files over 16KB in size..." + find ./pkg -size +16k -type f \ + -not -name '*.br' \ + -not -name '*.png' \ + -exec ./find_best_brotli.sh "{}" \; || exit 1 +fi + diff --git a/server/web_ui/build_wasm_release.sh b/server/web_ui/build_wasm_release.sh deleted file mode 120000 index 44d02181d..000000000 --- a/server/web_ui/build_wasm_release.sh +++ /dev/null @@ -1 +0,0 @@ -build_wasm.sh \ No newline at end of file diff --git a/server/web_ui/find_best_brotli.sh b/server/web_ui/find_best_brotli.sh index 884c21d89..b704e4491 100755 --- a/server/web_ui/find_best_brotli.sh +++ b/server/web_ui/find_best_brotli.sh @@ -14,6 +14,7 @@ if [ $# -eq 0 ]; then fi filename=$1 +echo "#####################################" echo "Compressing $1" # Exit if the file doesn't exist diff --git a/server/web_ui/individual_build.sh b/server/web_ui/individual_build.sh new file mode 100755 index 000000000..59ab91e04 --- /dev/null +++ b/server/web_ui/individual_build.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e + +if [ ! -f ../individual_build.sh ]; then + echo "Please run from the package base directory!" + exit 1 +fi + +if [ -z "${BUILD_FLAGS}" ]; then + BUILD_FLAGS="--release" +fi + +if [ -z "$(which rsync)" ]; then + echo "Cannot find rsync which is needed to move things around, quitting!" + exit 1 +fi +if [ -z "$(which wasm-pack)" ]; then + echo "Cannot find wasm-pack which is needed to build the UI, quitting!" + exit 1 +fi + +mkdir -p ./pkg + +echo "Cleaning up WASM files before build..." +find ./pkg/ -name 'kanidmd*' -exec rm "{}" \; + +# we can disable this since we want it to expand +# shellcheck disable=SC2086 +wasm-pack build ${BUILD_FLAGS} --no-typescript --target web --mode no-install --no-pack + +echo "######################" +echo "Moving files around..." +echo "######################" +touch ./pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC && \ + rm ./pkg/.gitignore + +echo "######################" +echo "Moving files up into the webui pkg dir..." +echo "######################" +rsync -av pkg/* ../pkg/ + +echo "######################" +echo " Done!" +echo "######################" \ No newline at end of file diff --git a/server/web_ui/login_flows/Cargo.toml b/server/web_ui/login_flows/Cargo.toml new file mode 100644 index 000000000..524a3e107 --- /dev/null +++ b/server/web_ui/login_flows/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "kanidmd_web_ui_login_flows" +description = "Kanidm Server Web UI - Login Flows" +documentation = "https://docs.rs/kanidm/latest/kanidm/" + +version = { workspace = true } +authors = [ + "William Brown ", + "James Hodgkinson ", +] +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +gloo = { workspace = true } +js-sys = { workspace = true } +kanidm_proto = { workspace = true, features = ["wasm"] } +kanidmd_web_ui_shared = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde-wasm-bindgen = { workspace = true } +wasm-bindgen = { workspace = true } +wasm-bindgen-futures = { workspace = true } +url = { workspace = true } +uuid = { workspace = true } +yew = { workspace = true, features = ["csr"] } +yew-router = { workspace = true } +time = { workspace = true } +lazy_static.workspace = true +gloo-utils = { workspace = true } +web-sys = { workspace = true, features = [ + "CredentialsContainer", + "Location", + "Navigator", + "Window", +] } + +[dev-dependencies] +wasm-bindgen-test = { workspace = true } diff --git a/server/web_ui/login_flows/build_dev.sh b/server/web_ui/login_flows/build_dev.sh new file mode 100755 index 000000000..e3f10e598 --- /dev/null +++ b/server/web_ui/login_flows/build_dev.sh @@ -0,0 +1,2 @@ +#!/bin/sh +BUILD_FLAGS="--dev" ./build.sh diff --git a/server/web_ui/login_flows/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC b/server/web_ui/login_flows/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC new file mode 100644 index 000000000..e69de29bb diff --git a/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows.js b/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows.js new file mode 100644 index 000000000..1593ac057 --- /dev/null +++ b/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows.js @@ -0,0 +1,1147 @@ +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +let cachedBigInt64Memory0 = null; + +function getBigInt64Memory0() { + if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) { + cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer); + } + return cachedBigInt64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} + +let stack_pointer = 128; + +function addBorrowedObject(obj) { + if (stack_pointer == 1) throw new Error('out of js stack'); + heap[--stack_pointer] = obj; + return stack_pointer; +} +function __wbg_adapter_48(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb2ffaaf8eabe7e9e(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +function __wbg_adapter_51(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h5882a5a28fa681a9(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_54(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h4bfbb5dd67876597(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +/** +* This is the entry point of the web front end. +* +* This triggers the manager app to load and begin its event loop. +*/ +export function run_app() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.run_app(retptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +let cachedUint32Memory0 = null; + +function getUint32Memory0() { + if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) { + cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32Memory0; +} + +function getArrayJsValueFromWasm0(ptr, len) { + ptr = ptr >>> 0; + const mem = getUint32Memory0(); + const slice = mem.subarray(ptr / 4, ptr / 4 + len); + const result = []; + for (let i = 0; i < slice.length; i++) { + result.push(takeObject(slice[i])); + } + return result; +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbindgen_is_bigint = function(arg0) { + const ret = typeof(getObject(arg0)) === 'bigint'; + return ret; + }; + imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) { + const ret = getObject(arg0) === getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { + const ret = BigInt.asUintN(64, arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_in = function(arg0, arg1) { + const ret = getObject(arg0) in getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_setlistenerid_3183aae8fa5840fb = function(arg0, arg1) { + getObject(arg0).__yew_listener_id = arg1 >>> 0; + }; + imports.wbg.__wbg_listenerid_12315eee21527820 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_listener_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_subtreeid_e348577f7ef777e3 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setsubtreeid_d32e6327eef1f7fc = function(arg0, arg1) { + getObject(arg0).__yew_subtree_id = arg1 >>> 0; + }; + imports.wbg.__wbg_cachekey_b61393159c57fd7b = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_cache_key; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setcachekey_80183b7cfc421143 = function(arg0, arg1) { + getObject(arg0).__yew_subtree_cache_key = arg1 >>> 0; + }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { + const ret = getObject(arg0) == getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_number_new = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_getwithrefkey_5e6d9547403deab8 = function(arg0, arg1) { + const ret = getObject(arg0)[getObject(arg1)]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_841ac57cff3d672b = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_debug_783a3d4910bc24c7 = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.debug(...v0); + }; + imports.wbg.__wbg_error_71d6845bf00a930f = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.error(...v0); + }; + imports.wbg.__wbg_info_0d469cecacab90cb = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.info(...v0); + }; + imports.wbg.__wbg_log_1f7f93998ab961f7 = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.log(...v0); + }; + imports.wbg.__wbg_warn_0b90a269a514ae1d = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.warn(...v0); + }; + imports.wbg.__wbg_body_674aec4c1c0910cd = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createElementNS_119acf9e82482041 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createTextNode_2fd22cd7e543f938 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getElementById_cc0e0d931b0d9a28 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_querySelector_52ded52c20e23921 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).querySelector(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Element; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_namespaceURI_31718ed49b5343a3 = function(arg0, arg1) { + const ret = getObject(arg1).namespaceURI; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_classList_5f2fc1d67656292e = function(arg0) { + const ret = getObject(arg0).classList; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setinnerHTML_b089587252408b67 = function(arg0, arg1, arg2) { + getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_outerHTML_f7749ceff37b5832 = function(arg0, arg1) { + const ret = getObject(arg1).outerHTML; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_children_27ed308801b57d3f = function(arg0) { + const ret = getObject(arg0).children; + return addHeapObject(ret); + }; + imports.wbg.__wbg_removeAttribute_d8404da431968808 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setAttribute_e7e80b478b7b8b2f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_location_56243dba507f472d = function(arg0) { + const ret = getObject(arg0).location; + return addHeapObject(ret); + }; + imports.wbg.__wbg_history_3c2280e6b2a9316e = function() { return handleError(function (arg0) { + const ret = getObject(arg0).history; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_navigator_7c9103698acde322 = function(arg0) { + const ret = getObject(arg0).navigator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_localStorage_dbac11bd189e9fa0 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).localStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_sessionStorage_3b863b6e15dd2bdc = function() { return handleError(function (arg0) { + const ret = getObject(arg0).sessionStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_fetch_336b6f0cb426b46e = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_HtmlElement_6f4725d4677c7968 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_focus_dbcbbbb2a04c0e1f = function() { return handleError(function (arg0) { + getObject(arg0).focus(); + }, arguments) }; + imports.wbg.__wbg_add_3eafedc4b2a28db0 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).add(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_remove_8ae45e50cb58bb66 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).remove(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_get_2e9aab260014946d = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).get(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_set_b34caba58723c454 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_bubbles_63572b91f3885ef1 = function(arg0) { + const ret = getObject(arg0).bubbles; + return ret; + }; + imports.wbg.__wbg_cancelBubble_90d1c3aa2a76cbeb = function(arg0) { + const ret = getObject(arg0).cancelBubble; + return ret; + }; + imports.wbg.__wbg_composedPath_cf1bb5b8bcff496f = function(arg0) { + const ret = getObject(arg0).composedPath(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbg_href_d62a28e4fc1ab948 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_sethref_e5626365d7354fea = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).href = getStringFromWasm0(arg1, arg2); + }, arguments) }; + imports.wbg.__wbg_pathname_c8fd5c498079312d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_search_6c3c472e076ee010 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_hash_a1a795b89dda8e3d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_replace_5d1d2b7956cafd7b = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).replace(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_log_1d3ae0273d8f4f8a = function(arg0) { + console.log(getObject(arg0)); + }; + imports.wbg.__wbg_get_e66794f89dcd7828 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).get(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_state_745dc4814d321eb3 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).state; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_pushState_1145414a47c0b629 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).pushState(getObject(arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); + }, arguments) }; + imports.wbg.__wbg_headers_b439dcff02e808e5 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithstrandinit_cad5cd6038c7ff5d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_status_ac85a3142a84caa2 = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_headers_b70de86b8e989bc0 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_json_2a46ed5b7c4d30d1 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).json(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_ShadowRoot_b64337370f59fe2d = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ShadowRoot; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_host_e1c47c33975060d3 = function(arg0) { + const ret = getObject(arg0).host; + return addHeapObject(ret); + }; + imports.wbg.__wbg_href_17ed54b321396524 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_pathname_57290e07c6bc0683 = function(arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_search_2ff3bb9114e0ca34 = function(arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_hash_2b57e787945b2db0 = function(arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_sethash_41d6e65816639c62 = function(arg0, arg1, arg2) { + getObject(arg0).hash = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_new_a76f6bcb38f791ea = function() { return handleError(function (arg0, arg1) { + const ret = new URL(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_newwithbase_79b8cac27ce631ac = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = new URL(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_addEventListener_a5963e26cd7b176b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbg_removeEventListener_782040b4432709cb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); + }, arguments) }; + imports.wbg.__wbg_href_47b90f0ddf3ddcd7 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_value_3c5f08ffc2b7d6f9 = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_0dc100d4b9908028 = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_getClientExtensionResults_b9108fbba9f54b38 = function(arg0) { + const ret = getObject(arg0).getClientExtensionResults(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getItem_ed8e218e51f1efeb = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_removeItem_02359267b311cb85 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeItem(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setItem_d002ee486462bfff = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_credentials_66b6baa89eb03c21 = function(arg0) { + const ret = getObject(arg0).credentials; + return addHeapObject(ret); + }; + imports.wbg.__wbg_parentNode_9e53f8b17eb98c9d = function(arg0) { + const ret = getObject(arg0).parentNode; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_parentElement_c75962bc9997ea5f = function(arg0) { + const ret = getObject(arg0).parentElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_lastChild_0cee692010bac6c2 = function(arg0) { + const ret = getObject(arg0).lastChild; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_nextSibling_304d9aac7c2774ae = function(arg0) { + const ret = getObject(arg0).nextSibling; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_setnodeValue_d1c8382910b45e04 = function(arg0, arg1, arg2) { + getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_textContent_c5d9e21ee03c63d4 = function(arg0, arg1) { + const ret = getObject(arg1).textContent; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_appendChild_51339d4cde00ee22 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_insertBefore_ffa01d4b747c95fc = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_removeChild_973429f368206138 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).removeChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlInputElement_31b50e0cf542c524 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLInputElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_checked_5ccb3a66eb054121 = function(arg0) { + const ret = getObject(arg0).checked; + return ret; + }; + imports.wbg.__wbg_setchecked_e5a50baea447b8a8 = function(arg0, arg1) { + getObject(arg0).checked = arg1 !== 0; + }; + imports.wbg.__wbg_value_9423da9d988ee8cf = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_1f95e61cbc382f7f = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_new_898a68150f225f2e = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) { + const ret = getObject(arg0).next; + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) { + const ret = getObject(arg0).next(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() { + const ret = Symbol.iterator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_set_502d29070ea18557 = function(arg0, arg1, arg2) { + getObject(arg0)[arg1 >>> 0] = takeObject(arg2); + }; + imports.wbg.__wbg_from_d7c216d4616bb368 = function(arg0) { + const ret = Array.from(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function(arg0) { + const ret = Array.isArray(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_push_ca1c26067ef907ac = function(arg0, arg1) { + const ret = getObject(arg0).push(getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_Error_ab19e20608ea43c7 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Error; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_message_48bacc5ea57d74ee = function(arg0) { + const ret = getObject(arg0).message; + return addHeapObject(ret); + }; + imports.wbg.__wbg_name_8f734cbbd6194153 = function(arg0) { + const ret = getObject(arg0).name; + return addHeapObject(ret); + }; + imports.wbg.__wbg_toString_1c056108b87ba68b = function(arg0) { + const ret = getObject(arg0).toString(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isSafeInteger_bb8e18dd21c97288 = function(arg0) { + const ret = Number.isSafeInteger(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_entries_e51f29c7bba0c054 = function(arg0) { + const ret = Object.entries(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_is_205d914af04a8faa = function(arg0, arg1) { + const ret = Object.is(getObject(arg0), getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_f7e06ee3c11698eb = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_b2267541e2a73865 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Uint8Array; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) { + const v = getObject(arg1); + const ret = typeof(v) === 'bigint' ? v : undefined; + getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1392 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 492, __wbg_adapter_48); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1771 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 634, __wbg_adapter_51); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1854 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 671, __wbg_adapter_54); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedBigInt64Memory0 = null; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('kanidmd_web_ui_login_flows_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows_bg.wasm b/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows_bg.wasm new file mode 100644 index 000000000..80ba60887 Binary files /dev/null and b/server/web_ui/login_flows/pkg/kanidmd_web_ui_login_flows_bg.wasm differ diff --git a/server/web_ui/login_flows/pkg/wasmloader_login_flows.js b/server/web_ui/login_flows/pkg/wasmloader_login_flows.js new file mode 100644 index 000000000..d1bf2a12c --- /dev/null +++ b/server/web_ui/login_flows/pkg/wasmloader_login_flows.js @@ -0,0 +1,7 @@ +// loads the module which loads the WASM. It's loaders all the way down. +import init, { run_app } from '/pkg/kanidmd_web_ui_login_flows.js'; +async function main() { + await init('/pkg/kanidmd_web_ui_login_flows_bg.wasm'); + run_app(); +} +main() \ No newline at end of file diff --git a/server/web_ui/src/login/mod.rs b/server/web_ui/login_flows/src/components.rs similarity index 84% rename from server/web_ui/src/login/mod.rs rename to server/web_ui/login_flows/src/components.rs index 7afa628d4..fc3c2aecd 100644 --- a/server/web_ui/src/login/mod.rs +++ b/server/web_ui/login_flows/src/components.rs @@ -1,3 +1,5 @@ +//! Login flow components + // use anyhow::Error; use gloo::console; use kanidm_proto::v1::{ @@ -5,39 +7,78 @@ use kanidm_proto::v1::{ AuthStep, }; use kanidm_proto::webauthn::PublicKeyCredential; +use kanidmd_web_ui_shared::utils::{autofocus, do_footer, window}; +use kanidmd_web_ui_shared::{ + add_body_form_classes, fetch_session_valid, logo_img, remove_body_form_classes, SessionStatus, +}; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::{spawn_local, JsFuture}; use web_sys::CredentialRequestOptions; use yew::prelude::*; use yew::virtual_dom::VNode; -use yew_router::prelude::*; -use crate::constants::{CLASS_BUTTON_DARK, CLASS_DIV_LOGIN_BUTTON, CLASS_DIV_LOGIN_FIELD}; -use crate::error::FetchError; -use crate::{do_request, models, utils, RequestMethod}; +use kanidmd_web_ui_shared::constants::{ + CLASS_BUTTON_DARK, CLASS_DIV_LOGIN_BUTTON, CLASS_DIV_LOGIN_FIELD, CSS_ALERT_DANGER, + URL_USER_HOME, +}; +use kanidmd_web_ui_shared::models::{ + self, clear_bearer_token, get_bearer_token, get_login_hint, pop_login_hint, + pop_login_remember_me, pop_return_location, push_login_remember_me, set_bearer_token, +}; +use kanidmd_web_ui_shared::{do_request, error::FetchError, utils, RequestMethod}; +use yew_router::BrowserRouter; +#[derive(Clone)] pub struct LoginApp { state: LoginState, } -#[derive(Debug, PartialEq, Clone)] +impl Default for LoginApp { + fn default() -> Self { + Self { + state: LoginState::InitLogin { + enable: true, + remember_me: false, + username: String::new(), + }, + } + } +} + +#[derive(PartialEq, Clone, Copy)] pub enum LoginWorkflow { Login, Reauth, } -#[derive(PartialEq, Properties)] +impl std::fmt::Display for LoginWorkflow { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + LoginWorkflow::Login => "LoginWorkflow::Login", + LoginWorkflow::Reauth => "LoginWorkflow::Reauth", + }) + } +} + +impl Default for LoginWorkflow { + fn default() -> Self { + Self::Login + } +} + +#[derive(PartialEq, Properties, Default)] pub struct LoginAppProps { pub workflow: LoginWorkflow, } -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Copy)] enum TotpState { Enabled, Disabled, Invalid, } +#[derive(Clone)] enum LoginState { InitLogin { enable: bool, @@ -82,6 +123,7 @@ pub enum LoginAppMsg { Select(usize), // DoNothing, UnknownUser, + AlreadyAuthenticated, Error { emsg: String, kopid: Option }, } @@ -94,7 +136,22 @@ impl From for LoginAppMsg { } } +impl From for LoginAppMsg { + fn from(s: SessionStatus) -> Self { + match s { + SessionStatus::TokenValid => LoginAppMsg::AlreadyAuthenticated, + SessionStatus::LoginRequired => LoginAppMsg::Begin, + SessionStatus::Error { emsg, kopid } => LoginAppMsg::Error { emsg, kopid }, + } + } +} + impl LoginApp { + /// Validate that the current auth token's OK + async fn fetch_session_valid() -> Result { + fetch_session_valid().await.map(|v| v.into()) + } + async fn auth_init(username: String) -> Result { let authreq = AuthRequest { step: AuthStep::Init2 { @@ -138,11 +195,11 @@ impl LoginApp { if status == 200 { let state: AuthResponse = serde_wasm_bindgen::from_value(value) - .expect_throw("Invalid response type - auth_init::AuthResponse"); + .expect_throw("Invalid response type during reauth_init::AuthResponse"); Ok(LoginAppMsg::Next(state)) } else if status == 404 { console::error!(format!( - "User not found: {:?}. Operation ID: {:?}", + "User not found during reauth_init: {:?}. Operation ID: {:?}", value.as_string(), kopid )); @@ -180,8 +237,9 @@ impl LoginApp { fn button_start_again(&self, ctx: &Context) -> VNode { html! {
- // TODO: this doesn't seem to work if you failed to login - +
} } @@ -220,7 +278,7 @@ impl LoginApp { html! {
- +
+
+ } +} diff --git a/server/web_ui/src/utils.rs b/server/web_ui/shared/src/utils.rs similarity index 89% rename from server/web_ui/src/utils.rs rename to server/web_ui/shared/src/utils.rs index 3c189844b..89b7aa8df 100644 --- a/server/web_ui/src/utils.rs +++ b/server/web_ui/shared/src/utils.rs @@ -1,4 +1,5 @@ use gloo::console; + use url::Url; use wasm_bindgen::prelude::*; use wasm_bindgen::{JsCast, UnwrapThrowExt}; @@ -7,6 +8,8 @@ use web_sys::{Document, HtmlElement, HtmlInputElement, Window}; use yew::virtual_dom::VNode; use yew::{html, Html}; +use crate::constants::{CSS_ALERT_DANGER, CSS_PAGE_HEADER}; + pub fn window() -> Window { web_sys::window().expect_throw("Unable to retrieve window") } @@ -77,7 +80,7 @@ pub fn get_value_from_element_id(id: &str) -> Option { .map(|element| element.value()) } -#[wasm_bindgen(raw_module = "/pkg/wasmloader.js")] +#[wasm_bindgen(raw_module = "/pkg/shared.js")] extern "C" { pub fn modal_hide_by_id(m: &str); } @@ -93,15 +96,18 @@ pub fn do_footer() -> VNode { } } -pub fn do_alert_error(alert_title: &str, alert_message: Option<&str>) -> Html { +pub fn do_alert_error(alert_title: &str, alert_message: Option<&str>, dismissable: bool) -> Html { html! {
-
@@ -110,7 +116,7 @@ pub fn do_alert_error(alert_title: &str, alert_message: Option<&str>) -> Html { pub fn do_page_header(page_title: &str) -> Html { html! { -
+

{ page_title }

} diff --git a/server/web_ui/static/external/bootstrap.bundle.min.js b/server/web_ui/shared/static/external/bootstrap.bundle.min.js similarity index 100% rename from server/web_ui/static/external/bootstrap.bundle.min.js rename to server/web_ui/shared/static/external/bootstrap.bundle.min.js diff --git a/server/web_ui/static/external/bootstrap.bundle.min.js.map b/server/web_ui/shared/static/external/bootstrap.bundle.min.js.map similarity index 100% rename from server/web_ui/static/external/bootstrap.bundle.min.js.map rename to server/web_ui/shared/static/external/bootstrap.bundle.min.js.map diff --git a/server/web_ui/static/external/bootstrap.min.css b/server/web_ui/shared/static/external/bootstrap.min.css similarity index 100% rename from server/web_ui/static/external/bootstrap.min.css rename to server/web_ui/shared/static/external/bootstrap.min.css diff --git a/server/web_ui/static/external/bootstrap.min.css.map b/server/web_ui/shared/static/external/bootstrap.min.css.map similarity index 100% rename from server/web_ui/static/external/bootstrap.min.css.map rename to server/web_ui/shared/static/external/bootstrap.min.css.map diff --git a/server/web_ui/static/external/confetti.js b/server/web_ui/shared/static/external/confetti.js similarity index 100% rename from server/web_ui/static/external/confetti.js rename to server/web_ui/shared/static/external/confetti.js diff --git a/server/web_ui/static/img/apple-touch-icon.png b/server/web_ui/shared/static/img/apple-touch-icon.png similarity index 100% rename from server/web_ui/static/img/apple-touch-icon.png rename to server/web_ui/shared/static/img/apple-touch-icon.png diff --git a/server/web_ui/static/img/favicon.png b/server/web_ui/shared/static/img/favicon.png similarity index 100% rename from server/web_ui/static/img/favicon.png rename to server/web_ui/shared/static/img/favicon.png diff --git a/server/web_ui/static/img/icon-accounts.svg b/server/web_ui/shared/static/img/icon-accounts.svg similarity index 100% rename from server/web_ui/static/img/icon-accounts.svg rename to server/web_ui/shared/static/img/icon-accounts.svg diff --git a/server/web_ui/static/img/icon-groups.svg b/server/web_ui/shared/static/img/icon-groups.svg similarity index 100% rename from server/web_ui/static/img/icon-groups.svg rename to server/web_ui/shared/static/img/icon-groups.svg diff --git a/server/web_ui/static/img/icon-oauth2.svg b/server/web_ui/shared/static/img/icon-oauth2.svg similarity index 100% rename from server/web_ui/static/img/icon-oauth2.svg rename to server/web_ui/shared/static/img/icon-oauth2.svg diff --git a/server/web_ui/static/img/icon-person.svg b/server/web_ui/shared/static/img/icon-person.svg similarity index 100% rename from server/web_ui/static/img/icon-person.svg rename to server/web_ui/shared/static/img/icon-person.svg diff --git a/server/web_ui/static/img/icon-robot.svg b/server/web_ui/shared/static/img/icon-robot.svg similarity index 100% rename from server/web_ui/static/img/icon-robot.svg rename to server/web_ui/shared/static/img/icon-robot.svg diff --git a/server/web_ui/static/img/kani-waving.svg b/server/web_ui/shared/static/img/kani-waving.svg similarity index 100% rename from server/web_ui/static/img/kani-waving.svg rename to server/web_ui/shared/static/img/kani-waving.svg diff --git a/server/web_ui/static/img/logo-180.png b/server/web_ui/shared/static/img/logo-180.png similarity index 100% rename from server/web_ui/static/img/logo-180.png rename to server/web_ui/shared/static/img/logo-180.png diff --git a/server/web_ui/static/img/logo-192.png b/server/web_ui/shared/static/img/logo-192.png similarity index 100% rename from server/web_ui/static/img/logo-192.png rename to server/web_ui/shared/static/img/logo-192.png diff --git a/server/web_ui/static/img/logo-256.png b/server/web_ui/shared/static/img/logo-256.png similarity index 100% rename from server/web_ui/static/img/logo-256.png rename to server/web_ui/shared/static/img/logo-256.png diff --git a/server/web_ui/static/img/logo-512.png b/server/web_ui/shared/static/img/logo-512.png similarity index 100% rename from server/web_ui/static/img/logo-512.png rename to server/web_ui/shared/static/img/logo-512.png diff --git a/server/web_ui/static/img/logo-square.svg b/server/web_ui/shared/static/img/logo-square.svg similarity index 100% rename from server/web_ui/static/img/logo-square.svg rename to server/web_ui/shared/static/img/logo-square.svg diff --git a/server/web_ui/shared/static/shared.js b/server/web_ui/shared/static/shared.js new file mode 100644 index 000000000..90cd9d4b0 --- /dev/null +++ b/server/web_ui/shared/static/shared.js @@ -0,0 +1,6 @@ +// This is easier to have in JS than in WASM +export function modal_hide_by_id(m) { + var elem = document.getElementById(m); + var modal = bootstrap.Modal.getInstance(elem); + modal.hide(); +}; \ No newline at end of file diff --git a/server/web_ui/static/style.css b/server/web_ui/shared/static/style.css similarity index 96% rename from server/web_ui/static/style.css rename to server/web_ui/shared/static/style.css index 0a6252d85..e9e471d28 100644 --- a/server/web_ui/static/style.css +++ b/server/web_ui/shared/static/style.css @@ -129,6 +129,13 @@ body { right: 1rem; } +.navbar-toggler-img { + width: 50px; + height: 50px; + padding: 0px; + margin: 0px; +} + .navbar .form-control { padding: 0.75rem 1rem; border-width: 0; @@ -236,3 +243,8 @@ body { -o-transition: none !important; transition: none !important; } + +.oauth2-img { + max-width: 150px; + max-height: 150px; +} \ No newline at end of file diff --git a/server/web_ui/src/components/mod.rs b/server/web_ui/src/components/mod.rs deleted file mode 100644 index 88eb67568..000000000 --- a/server/web_ui/src/components/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -use yew::prelude::*; -use yew::Html; - -pub mod admin_accounts; -pub mod admin_groups; -pub mod admin_menu; -pub mod admin_oauth2; -pub mod change_unix_password; -pub mod create_reset_code; -pub mod totpdisplay; - -/// creates the "Kanidm is alpha" banner -pub fn alpha_warning_banner() -> Html { - html!( - - ) -} diff --git a/server/web_ui/src/lib.rs b/server/web_ui/src/lib.rs deleted file mode 100644 index ebcac7eb1..000000000 --- a/server/web_ui/src/lib.rs +++ /dev/null @@ -1,134 +0,0 @@ -#![recursion_limit = "256"] -#![deny(warnings)] -#![warn(unused_extern_crates)] -#![deny(clippy::todo)] -#![deny(clippy::unimplemented)] -#![deny(clippy::unwrap_used)] -#![deny(clippy::expect_used)] -#![deny(clippy::panic)] -#![deny(clippy::unreachable)] -#![deny(clippy::await_holding_lock)] -#![deny(clippy::needless_pass_by_value)] -#![deny(clippy::trivially_copy_pass_by_ref)] -// Needed as yew-router::Routable uses std::collection::HashMap -#![allow(clippy::disallowed_types)] - -use error::FetchError; -use gloo::console; -use kanidm_proto::constants::{APPLICATION_JSON, KSESSIONID}; -use serde::{Deserialize, Serialize}; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::JsFuture; -use web_sys::{Headers, Request, RequestInit, RequestMode, Response}; - -#[macro_use] -mod macros; - -mod constants; -mod credential; -mod error; -mod login; -mod manager; -mod models; -mod oauth2; -mod utils; -mod views; - -mod components; - -/// This is the entry point of the web front end. This triggers the manager app to load and begin -/// it's event loop. -#[cfg_attr(target_arch = "wasm32", wasm_bindgen)] -pub fn run_app() -> Result<(), JsValue> { - yew::Renderer::::new().render(); - Ok(()) -} - -#[derive(Serialize, Deserialize, Eq, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum RequestMethod { - GET, - POST, - PUT, -} - -impl ToString for RequestMethod { - fn to_string(&self) -> String { - match self { - RequestMethod::PUT => "PUT".to_string(), - RequestMethod::POST => "POST".to_string(), - RequestMethod::GET => "GET".to_string(), - } - } -} - -/// Build and send a request to the backend, with some standard headers and pull back -/// (kopid, status, json, headers) -pub async fn do_request( - uri: &str, - method: RequestMethod, - body: Option, -) -> Result<(Option, u16, JsValue, Headers), FetchError> { - let mut opts = RequestInit::new(); - opts.method(&method.to_string()); - opts.mode(RequestMode::SameOrigin); - opts.credentials(web_sys::RequestCredentials::SameOrigin); - - if let Some(body) = body { - #[cfg(debug_assertions)] - if method == RequestMethod::GET { - gloo::console::debug!("This seems odd, you've supplied a body with a GET request?") - } - opts.body(Some(&body)); - } - - let request = Request::new_with_str_and_init(uri, &opts)?; - request - .headers() - .set(crate::constants::CONTENT_TYPE, APPLICATION_JSON) - .expect_throw("failed to set content-type header"); - - if let Some(sessionid) = models::pop_auth_session_id() { - request - .headers() - .set(KSESSIONID, &sessionid) - .expect_throw("failed to set auth session id header"); - } - - if let Some(bearer_token) = models::get_bearer_token() { - request - .headers() - .set("authorization", &bearer_token) - .expect_throw("failed to set authorisation header"); - } - - let window = utils::window(); - let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?; - let resp: Response = resp_value.dyn_into().expect_throw("Invalid response type"); - let status = resp.status(); - let headers: Headers = resp.headers(); - - if let Some(sessionid) = headers.get(KSESSIONID).ok().flatten() { - models::push_auth_session_id(sessionid); - } - - let kopid = headers.get("x-kanidm-opid").ok().flatten(); - - let body = match resp.json() { - Ok(json_future) => match JsFuture::from(json_future).await { - Ok(body) => body, - Err(e) => { - let e_msg = format!("future json error -> {:?}", e); - console::error!(e_msg.as_str()); - JsValue::NULL - } - }, - Err(e) => { - let e_msg = format!("response json error -> {:?}", e); - console::error!(e_msg.as_str()); - JsValue::NULL - } - }; - - Ok((kopid, status, body, headers)) -} diff --git a/server/web_ui/src/models/mod.rs b/server/web_ui/src/models/mod.rs deleted file mode 100644 index 09646df54..000000000 --- a/server/web_ui/src/models/mod.rs +++ /dev/null @@ -1,145 +0,0 @@ -#[cfg(debug_assertions)] -use gloo::console; -use gloo::storage::{ - LocalStorage as PersistentStorage, SessionStorage as TemporaryStorage, Storage, -}; -use kanidm_proto::oauth2::AuthorisationRequest; -use kanidm_proto::v1::{CUSessionToken, CUStatus}; -use serde::{Deserialize, Serialize}; -use wasm_bindgen::UnwrapThrowExt; -use yew_router::navigator::Navigator; - -use crate::manager::Route; -use crate::views::ViewRoute; - -pub fn set_bearer_token(r: String) { - PersistentStorage::set("bearer_token", r).expect_throw("failed to set bearer_token"); -} - -pub fn get_bearer_token() -> Option { - let l: Result = PersistentStorage::get("bearer_token"); - #[cfg(debug_assertions)] - console::debug!(format!( - "login_hint::get_login_remember_me -> present={:?}", - l.is_ok() - ) - .as_str()); - l.ok() -} - -pub fn clear_bearer_token() { - PersistentStorage::delete("bearer_token"); -} - -pub fn push_auth_session_id(r: String) { - TemporaryStorage::set("auth_session_id", r) - .expect_throw("failed to set auth_session_id in temporary storage"); -} - -pub fn pop_auth_session_id() -> Option { - let l: Result = TemporaryStorage::get("auth_session_id"); - #[cfg(debug_assertions)] - console::debug!(format!("auth_session_id -> {:?}", l).as_str()); - TemporaryStorage::delete("auth_session_id"); - l.ok() -} - -#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] -pub enum Location { - Manager(Route), - Views(ViewRoute), -} - -impl Location { - pub(crate) fn goto(self, navigator: &Navigator) { - match self { - Location::Manager(r) => navigator.push(&r), - Location::Views(r) => navigator.push(&r), - } - } -} - -pub fn push_return_location(l: Location) { - TemporaryStorage::set("return_location", l) - .expect_throw("failed to set return_location in temporary storage"); -} - -pub fn pop_return_location() -> Location { - let l: Result = TemporaryStorage::get("return_location"); - #[cfg(debug_assertions)] - console::debug!(format!("return_location -> {:?}", l).as_str()); - TemporaryStorage::delete("return_location"); - l.unwrap_or(Location::Manager(Route::Landing)) -} - -pub fn push_oauth2_authorisation_request(r: AuthorisationRequest) { - TemporaryStorage::set("oauth2_authorisation_request", r) - .expect_throw("failed to set oauth2_authorisation_request in temporary storage"); -} - -pub fn pop_oauth2_authorisation_request() -> Option { - let l: Result = TemporaryStorage::get("oauth2_authorisation_request"); - #[cfg(debug_assertions)] - console::debug!(format!("oauth2_authorisation_request -> {:?}", l).as_str()); - TemporaryStorage::delete("oauth2_authorisation_request"); - l.ok() -} - -pub fn push_login_hint(r: String) { - TemporaryStorage::set("login_hint", r).expect_throw("failed to set login hint"); -} - -pub fn get_login_hint() -> Option { - let l: Result = TemporaryStorage::get("login_hint"); - #[cfg(debug_assertions)] - console::debug!(format!("login_hint::get_login_hint -> {:?}", l).as_str()); - l.ok() -} - -pub fn pop_login_hint() -> Option { - let l: Result = TemporaryStorage::get("login_hint"); - #[cfg(debug_assertions)] - console::debug!(format!("login_hint::pop_login_hint -> {:?}", l).as_str()); - TemporaryStorage::delete("login_hint"); - l.ok() -} - -pub fn push_login_remember_me(r: String) { - PersistentStorage::set("login_remember_me", r).expect_throw("failed to set login remember me"); -} - -pub fn get_login_remember_me() -> Option { - let l: Result = PersistentStorage::get("login_remember_me"); - #[cfg(debug_assertions)] - console::debug!(format!("login_hint::get_login_remember_me -> {:?}", l).as_str()); - l.ok() -} - -pub fn pop_login_remember_me() -> Option { - let l: Result = PersistentStorage::get("login_remember_me"); - #[cfg(debug_assertions)] - console::debug!(format!("login_hint::pop_login_remember_me -> {:?}", l).as_str()); - PersistentStorage::delete("login_remember_me"); - l.ok() -} - -/// Pushes the "cred_update_session" element into the browser's temporary storage -pub fn push_cred_update_session(s: (CUSessionToken, CUStatus)) { - TemporaryStorage::set("cred_update_session", s) - .expect_throw("failed to set cred session token"); -} - -/// Pulls the "cred_update_session" element from the browser's temporary storage -pub fn get_cred_update_session() -> Option<(CUSessionToken, CUStatus)> { - let l: Result<(CUSessionToken, CUStatus), _> = TemporaryStorage::get("cred_update_session"); - l.ok() -} - -/* -/// pops the "cred_update_session" element from the browser's temporary storage -pub fn pop_cred_update_session() -> Option<(CUSessionToken, CUStatus)> { - let l: Result<(CUSessionToken, CUStatus), _> = TemporaryStorage::get("cred_update_session"); - TemporaryStorage::delete("cred_update_session"); - l.ok() -} -*/ diff --git a/server/web_ui/Cargo.toml b/server/web_ui/user/Cargo.toml similarity index 81% rename from server/web_ui/Cargo.toml rename to server/web_ui/user/Cargo.toml index 96cab747b..4c13640bc 100644 --- a/server/web_ui/Cargo.toml +++ b/server/web_ui/user/Cargo.toml @@ -1,28 +1,27 @@ [package] -name = "kanidmd_web_ui" -description = "Kanidm Server Web User Interface" +name = "kanidmd_web_ui_user" +description = "Kanidm Server Web UI - User-Facing" documentation = "https://docs.rs/kanidm/latest/kanidm/" -version = "1.1.0-rc.14-dev" +version = { workspace = true } authors = [ "William Brown ", "James Hodgkinson ", ] -rust-version = "1.66" -edition = "2021" -license = "MPL-2.0" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" +rust-version = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } [lib] crate-type = ["cdylib", "rlib"] -test = true -doctest = false [dependencies] gloo = { workspace = true } js-sys = { workspace = true } kanidm_proto = { workspace = true, features = ["wasm"] } +kanidmd_web_ui_shared = { workspace = true } qrcode = { workspace = true, features = ["svg"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } @@ -38,6 +37,7 @@ gloo-timers = "0.3.0" wasm-timer = "0.2.5" regex.workspace = true lazy_static.workspace = true +gloo-utils = { workspace = true } [dependencies.web-sys] workspace = true diff --git a/server/web_ui/user/build_dev.sh b/server/web_ui/user/build_dev.sh new file mode 100755 index 000000000..e3f10e598 --- /dev/null +++ b/server/web_ui/user/build_dev.sh @@ -0,0 +1,2 @@ +#!/bin/sh +BUILD_FLAGS="--dev" ./build.sh diff --git a/server/web_ui/user/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC b/server/web_ui/user/pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC new file mode 100644 index 000000000..e69de29bb diff --git a/server/web_ui/user/pkg/LICENSE.md b/server/web_ui/user/pkg/LICENSE.md new file mode 100644 index 000000000..74dee48ce --- /dev/null +++ b/server/web_ui/user/pkg/LICENSE.md @@ -0,0 +1,327 @@ +# Mozilla Public License Version 2.0 + +1. Definitions + +--- + +1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation +of, or owns Covered Software. + +1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a +Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" means Covered Software of a particular Contributor. + +1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the +notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source +Code Form, in each case including portions thereof. + +1.5. "Incompatible With Secondary Licenses" means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" means any form of the work other than Source Code Form. + +1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate +file or files, that is not Covered Software. + +1.8. "License" means this document. + +1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the +time of the initial grant or subsequently, any and all of the rights conveyed by this License. + +1.10. "Modifications" means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, +method, process, and apparatus claims, in any patent Licensable by such Contributor that would be +infringed, but for the grant of the License, by the making, using, selling, offering for sale, +having made, import, or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser +General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any +later versions of those licenses. + +1.13. "Source Code Form" means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. +For legal entities, "You" includes any entity that controls, is controlled by, or is under common +control with You. For purposes of this definition, "control" means (a) the power, direct or +indirect, to cause the direction or management of such entity, whether by contract or otherwise, or +(b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of +such entity. + +2. License Grants and Conditions + +--- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) Licensable by such +Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise +exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger +Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, +and otherwise transfer either its Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution become effective for each +Contribution on the date the Contributor first distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under this License. No additional +rights or licenses will be implied from the distribution or licensing of Covered Software under this +License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: + +(a) for any code that a Contributor has removed from Covered Software; or + +(b) for infringements caused by: (i) Your and any other third party's modifications of Covered +Software, or (ii) the combination of its Contributions with other software (except as part of its +Contributor Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of its Contributions. + +This License does not grant any rights in the trademarks, service marks, or logos of any Contributor +(except as may be necessary to comply with the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to distribute the Covered Software +under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary +License (if permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its Contributions are its original +creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this +License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under applicable copyright doctrines of +fair use, fair dealing, or other equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. + +3. Responsibilities + +--- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any Modifications that You +create or to which You contribute, must be under the terms of this License. You must inform +recipients that the Source Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not attempt to alter or restrict +the recipients' rights in the Source Code Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code Form, as described in Section +3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source +Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution +to the recipient; and + +(b) You may distribute such Executable Form under the terms of this License, or sublicense it under +different terms, provided that the license for the Executable Form does not attempt to limit or +alter the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, provided that You also +comply with the requirements of this License for the Covered Software. If the Larger Work is a +combination of Covered Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this License permits You to +additionally distribute such Covered Software under the terms of such Secondary License(s), so that +the recipient of the Larger Work may, at their option, further distribute the Covered Software under +the terms of either this License or such Secondary License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices (including copyright notices, +patent notices, disclaimers of warranty, or limitations of liability) contained within the Source +Code Form of the Covered Software, except that You may alter any license notices to the extent +required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability +obligations to one or more recipients of Covered Software. However, You may do so only on Your own +behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such +warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree +to indemnify every Contributor for any liability incurred by such Contributor as a result of +warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of +warranty and limitations of liability specific to any jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + +--- + +If it is impossible for You to comply with any of the terms of this License with respect to some or +all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply +with the terms of this License to the maximum extent possible; and (b) describe the limitations and +the code they affect. Such description must be placed in a text file included with all distributions +of the Covered Software under this License. Except to the extent prohibited by statute or +regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be +able to understand it. + +5. Termination + +--- + +5.1. The rights granted under this License will terminate automatically if You fail to comply with +any of its terms. However, if You become compliant, then the rights granted under this License from +a particular Contributor are reinstated (a) provisionally, unless and until such Contributor +explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor +fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an +ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this +is the first time You have received notice of non-compliance with this License from such +Contributor, and You become compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent infringement claim +(excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a +Contributor Version directly or indirectly infringes any patent, then the rights granted to You by +any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements +(excluding distributors and resellers) which have been validly granted by You or Your distributors +under this License prior to termination shall survive termination. + +--- + +- + - +- + 6. Disclaimer of Warranty * +- ------------------------- * +- + - +- Covered Software is provided under this License on an "as is" * +- basis, without warranty of any kind, either expressed, implied, or * +- statutory, including, without limitation, warranties that the * +- Covered Software is free of defects, merchantable, fit for a * +- particular purpose or non-infringing. The entire risk as to the * +- quality and performance of the Covered Software is with You. * +- Should any Covered Software prove defective in any respect, You * +- (not any Contributor) assume the cost of any necessary servicing, * +- repair, or correction. This disclaimer of warranty constitutes an * +- essential part of this License. No use of any Covered Software is * +- authorized under this License except under this disclaimer. * +- + - + +--- + +--- + +- + - +- + 7. Limitation of Liability * +- -------------------------- * +- + - +- Under no circumstances and under no legal theory, whether tort * +- (including negligence), contract, or otherwise, shall any * +- Contributor, or anyone who distributes Covered Software as * +- permitted above, be liable to You for any direct, indirect, * +- special, incidental, or consequential damages of any character * +- including, without limitation, damages for lost profits, loss of * +- goodwill, work stoppage, computer failure or malfunction, or any * +- and all other commercial damages or losses, even if such party * +- shall have been informed of the possibility of such damages. This * +- limitation of liability shall not apply to liability for death or * +- personal injury resulting from such party's negligence to the * +- extent applicable law prohibits such limitation. Some * +- jurisdictions do not allow the exclusion or limitation of * +- incidental or consequential damages, so this exclusion and * +- limitation may not apply to You. * +- + - + +--- + +8. Litigation + +--- + +Any litigation relating to this License may be brought only in the courts of a jurisdiction where +the defendant maintains its principal place of business and such litigation shall be governed by +laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this +Section shall prevent a party's ability to bring cross-claims or counter-claims. + +9. Miscellaneous + +--- + +This License represents the complete agreement concerning the subject matter hereof. If any +provision of this License is held to be unenforceable, such provision shall be reformed only to the +extent necessary to make it enforceable. Any law or regulation which provides that the language of a +contract shall be construed against the drafter shall not be used to construe this License against a +Contributor. + +10. Versions of the License + +--- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the +license steward has the right to modify or publish new versions of this License. Each version will +be given a distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version of the License under which +You originally received the Covered Software, or under the terms of any subsequent version published +by the license steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to create a new license for such +software, you may create and use a modified version of this License if you rename the license and +remove any references to the name of the license steward (except to note that such modified license +differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the +terms of this version of the License, the notice described in Exhibit B of this License must be +attached. + +## Exhibit A - Source Code Form License Notice + +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of +the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then You may include the +notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be +likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +## Exhibit B - "Incompatible With Secondary Licenses" Notice + +This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public +License, v. 2.0. diff --git a/server/web_ui/user/pkg/kanidmd_web_ui_user.js b/server/web_ui/user/pkg/kanidmd_web_ui_user.js new file mode 100644 index 000000000..da036d81c --- /dev/null +++ b/server/web_ui/user/pkg/kanidmd_web_ui_user.js @@ -0,0 +1,1206 @@ +import { modal_hide_by_id } from '/pkg/shared.js'; + +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); + +if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +let cachedBigInt64Memory0 = null; + +function getBigInt64Memory0() { + if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) { + cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer); + } + return cachedBigInt64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_48(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h29b65e42a9dd1ad6(arg0, arg1); +} + +let stack_pointer = 128; + +function addBorrowedObject(obj) { + if (stack_pointer == 1) throw new Error('out of js stack'); + heap[--stack_pointer] = obj; + return stack_pointer; +} +function __wbg_adapter_51(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h17983a2b133dd53c(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +function __wbg_adapter_54(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h5882a5a28fa681a9(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_57(arg0, arg1, arg2) { + try { + wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h1231c314c8a7204e(arg0, arg1, addBorrowedObject(arg2)); + } finally { + heap[stack_pointer++] = undefined; + } +} + +/** +* This is the entry point of the web front end. This triggers the manager app to load and begin +* its event loop. +*/ +export function run_app() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.run_app(retptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_exn_store(addHeapObject(e)); + } +} + +let cachedUint32Memory0 = null; + +function getUint32Memory0() { + if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) { + cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32Memory0; +} + +function getArrayJsValueFromWasm0(ptr, len) { + ptr = ptr >>> 0; + const mem = getUint32Memory0(); + const slice = mem.subarray(ptr / 4, ptr / 4 + len); + const result = []; + for (let i = 0; i < slice.length; i++) { + result.push(takeObject(slice[i])); + } + return result; +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbindgen_is_bigint = function(arg0) { + const ret = typeof(getObject(arg0)) === 'bigint'; + return ret; + }; + imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) { + const ret = getObject(arg0) === getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { + const ret = BigInt.asUintN(64, arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_in = function(arg0, arg1) { + const ret = getObject(arg0) in getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_clearTimeout_541ac0980ffcef74 = function(arg0) { + const ret = clearTimeout(takeObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_clearInterval_7f51e4380e64c6c5 = function(arg0) { + const ret = clearInterval(takeObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_setTimeout_7d81d052875b0f4f = function() { return handleError(function (arg0, arg1) { + const ret = setTimeout(getObject(arg0), arg1); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_setInterval_e227d4d8a9d44d66 = function() { return handleError(function (arg0, arg1) { + const ret = setInterval(getObject(arg0), arg1); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_modalhidebyid_5fcddcb8c6ea894f = function(arg0, arg1) { + modal_hide_by_id(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbg_setlistenerid_3183aae8fa5840fb = function(arg0, arg1) { + getObject(arg0).__yew_listener_id = arg1 >>> 0; + }; + imports.wbg.__wbg_listenerid_12315eee21527820 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_listener_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_subtreeid_e348577f7ef777e3 = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_id; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setsubtreeid_d32e6327eef1f7fc = function(arg0, arg1) { + getObject(arg0).__yew_subtree_id = arg1 >>> 0; + }; + imports.wbg.__wbg_cachekey_b61393159c57fd7b = function(arg0, arg1) { + const ret = getObject(arg1).__yew_subtree_cache_key; + getInt32Memory0()[arg0 / 4 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_setcachekey_80183b7cfc421143 = function(arg0, arg1) { + getObject(arg0).__yew_subtree_cache_key = arg1 >>> 0; + }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { + const ret = getObject(arg0) == getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_number_new = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbg_getwithrefkey_5e6d9547403deab8 = function(arg0, arg1) { + const ret = getObject(arg0)[getObject(arg1)]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_841ac57cff3d672b = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_debug_783a3d4910bc24c7 = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.debug(...v0); + }; + imports.wbg.__wbg_error_71d6845bf00a930f = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.error(...v0); + }; + imports.wbg.__wbg_warn_0b90a269a514ae1d = function(arg0, arg1) { + var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); + wasm.__wbindgen_free(arg0, arg1 * 4); + console.warn(...v0); + }; + imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_documentURI_4bff51077cdeeac1 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).documentURI; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_body_674aec4c1c0910cd = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_createElement_4891554b28d3388b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createElementNS_119acf9e82482041 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_createTextNode_2fd22cd7e543f938 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getElementById_cc0e0d931b0d9a28 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_querySelector_52ded52c20e23921 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).querySelector(getStringFromWasm0(arg1, arg2)); + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Element; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_namespaceURI_31718ed49b5343a3 = function(arg0, arg1) { + const ret = getObject(arg1).namespaceURI; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_classList_5f2fc1d67656292e = function(arg0) { + const ret = getObject(arg0).classList; + return addHeapObject(ret); + }; + imports.wbg.__wbg_setinnerHTML_b089587252408b67 = function(arg0, arg1, arg2) { + getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_outerHTML_f7749ceff37b5832 = function(arg0, arg1) { + const ret = getObject(arg1).outerHTML; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_children_27ed308801b57d3f = function(arg0) { + const ret = getObject(arg0).children; + return addHeapObject(ret); + }; + imports.wbg.__wbg_removeAttribute_d8404da431968808 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setAttribute_e7e80b478b7b8b2f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_instanceof_Window_9029196b662bc42a = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Window; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_document_f7ace2b956f30a4f = function(arg0) { + const ret = getObject(arg0).document; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_location_56243dba507f472d = function(arg0) { + const ret = getObject(arg0).location; + return addHeapObject(ret); + }; + imports.wbg.__wbg_history_3c2280e6b2a9316e = function() { return handleError(function (arg0) { + const ret = getObject(arg0).history; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_navigator_7c9103698acde322 = function(arg0) { + const ret = getObject(arg0).navigator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_localStorage_dbac11bd189e9fa0 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).localStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_sessionStorage_3b863b6e15dd2bdc = function() { return handleError(function (arg0) { + const ret = getObject(arg0).sessionStorage; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_fetch_336b6f0cb426b46e = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_HtmlElement_6f4725d4677c7968 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_focus_dbcbbbb2a04c0e1f = function() { return handleError(function (arg0) { + getObject(arg0).focus(); + }, arguments) }; + imports.wbg.__wbg_href_d62a28e4fc1ab948 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_sethref_e5626365d7354fea = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).href = getStringFromWasm0(arg1, arg2); + }, arguments) }; + imports.wbg.__wbg_pathname_c8fd5c498079312d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_search_6c3c472e076ee010 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_hash_a1a795b89dda8e3d = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_create_c7e40b6b88186cbf = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).create(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_state_745dc4814d321eb3 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).state; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_pushState_1145414a47c0b629 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { + getObject(arg0).pushState(getObject(arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); + }, arguments) }; + imports.wbg.__wbg_headers_b439dcff02e808e5 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithstrandinit_cad5cd6038c7ff5d = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_Response_fc4327dbfcdf5ced = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_status_ac85a3142a84caa2 = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_headers_b70de86b8e989bc0 = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_json_2a46ed5b7c4d30d1 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).json(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_instanceof_ShadowRoot_b64337370f59fe2d = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ShadowRoot; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_host_e1c47c33975060d3 = function(arg0) { + const ret = getObject(arg0).host; + return addHeapObject(ret); + }; + imports.wbg.__wbg_href_17ed54b321396524 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_pathname_57290e07c6bc0683 = function(arg0, arg1) { + const ret = getObject(arg1).pathname; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_search_2ff3bb9114e0ca34 = function(arg0, arg1) { + const ret = getObject(arg1).search; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setsearch_16b87f04ea0e6b80 = function(arg0, arg1, arg2) { + getObject(arg0).search = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_hash_2b57e787945b2db0 = function(arg0, arg1) { + const ret = getObject(arg1).hash; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_sethash_41d6e65816639c62 = function(arg0, arg1, arg2) { + getObject(arg0).hash = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_new_a76f6bcb38f791ea = function() { return handleError(function (arg0, arg1) { + const ret = new URL(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_newwithbase_79b8cac27ce631ac = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = new URL(getStringFromWasm0(arg0, arg1), getStringFromWasm0(arg2, arg3)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_newwithform_368648c82279d486 = function() { return handleError(function (arg0) { + const ret = new FormData(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_get_4c356dcef81d58a5 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).get(getStringFromWasm0(arg1, arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_HtmlInputElement_31b50e0cf542c524 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLInputElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_setchecked_e5a50baea447b8a8 = function(arg0, arg1) { + getObject(arg0).checked = arg1 !== 0; + }; + imports.wbg.__wbg_value_9423da9d988ee8cf = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_1f95e61cbc382f7f = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_target_f171e89c61e2bccf = function(arg0) { + const ret = getObject(arg0).target; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_bubbles_63572b91f3885ef1 = function(arg0) { + const ret = getObject(arg0).bubbles; + return ret; + }; + imports.wbg.__wbg_cancelBubble_90d1c3aa2a76cbeb = function(arg0) { + const ret = getObject(arg0).cancelBubble; + return ret; + }; + imports.wbg.__wbg_composedPath_cf1bb5b8bcff496f = function(arg0) { + const ret = getObject(arg0).composedPath(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_preventDefault_24104f3f0a54546a = function(arg0) { + getObject(arg0).preventDefault(); + }; + imports.wbg.__wbg_href_47b90f0ddf3ddcd7 = function(arg0, arg1) { + const ret = getObject(arg1).href; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_value_3c5f08ffc2b7d6f9 = function(arg0, arg1) { + const ret = getObject(arg1).value; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_setvalue_0dc100d4b9908028 = function(arg0, arg1, arg2) { + getObject(arg0).value = getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_getClientExtensionResults_b9108fbba9f54b38 = function(arg0) { + const ret = getObject(arg0).getClientExtensionResults(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_getItem_ed8e218e51f1efeb = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_removeItem_02359267b311cb85 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).removeItem(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_setItem_d002ee486462bfff = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_addEventListener_a5963e26cd7b176b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); + }, arguments) }; + imports.wbg.__wbg_removeEventListener_782040b4432709cb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); + }, arguments) }; + imports.wbg.__wbg_instanceof_HtmlFormElement_b57527983c7c1ada = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof HTMLFormElement; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_credentials_66b6baa89eb03c21 = function(arg0) { + const ret = getObject(arg0).credentials; + return addHeapObject(ret); + }; + imports.wbg.__wbg_parentNode_9e53f8b17eb98c9d = function(arg0) { + const ret = getObject(arg0).parentNode; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_parentElement_c75962bc9997ea5f = function(arg0) { + const ret = getObject(arg0).parentElement; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_lastChild_0cee692010bac6c2 = function(arg0) { + const ret = getObject(arg0).lastChild; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_nextSibling_304d9aac7c2774ae = function(arg0) { + const ret = getObject(arg0).nextSibling; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_setnodeValue_d1c8382910b45e04 = function(arg0, arg1, arg2) { + getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); + }; + imports.wbg.__wbg_textContent_c5d9e21ee03c63d4 = function(arg0, arg1) { + const ret = getObject(arg1).textContent; + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbg_appendChild_51339d4cde00ee22 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).appendChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_insertBefore_ffa01d4b747c95fc = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_removeChild_973429f368206138 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).removeChild(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_add_3eafedc4b2a28db0 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).add(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_remove_8ae45e50cb58bb66 = function() { return handleError(function (arg0, arg1, arg2) { + getObject(arg0).remove(getStringFromWasm0(arg1, arg2)); + }, arguments) }; + imports.wbg.__wbg_get_2e9aab260014946d = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg1).get(getStringFromWasm0(arg2, arg3)); + var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + var len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }, arguments) }; + imports.wbg.__wbg_set_b34caba58723c454 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_get_44be0491f933a435 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_fff51ee6522a1a18 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_new_898a68150f225f2e = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_newnoargs_581967eacc0e2604 = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_56693dbed0c32988 = function() { + const ret = new Map(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_526fc47e980da008 = function(arg0) { + const ret = getObject(arg0).next; + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_ddb3312ca1c4e32a = function() { return handleError(function (arg0) { + const ret = getObject(arg0).next(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_done_5c1f01fb660d73b5 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_1695675138684bd5 = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_iterator_97f0c81209c6c35a = function() { + const ret = Symbol.iterator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_97b561fb56f034b5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_cb65541d95d71282 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_b51585de1b234aff = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_1ff1d729e9aae938 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_5f4faef6c12b79ec = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_1d39714405582d3c = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_651f05c6a0944d1c = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_set_502d29070ea18557 = function(arg0, arg1, arg2) { + getObject(arg0)[arg1 >>> 0] = takeObject(arg2); + }; + imports.wbg.__wbg_from_d7c216d4616bb368 = function(arg0) { + const ret = Array.from(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isArray_4c24b343cb13cfb1 = function(arg0) { + const ret = Array.isArray(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_push_ca1c26067ef907ac = function(arg0, arg1) { + const ret = getObject(arg0).push(getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_39ac22089b74fddb = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_instanceof_Error_ab19e20608ea43c7 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Error; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_message_48bacc5ea57d74ee = function(arg0) { + const ret = getObject(arg0).message; + return addHeapObject(ret); + }; + imports.wbg.__wbg_name_8f734cbbd6194153 = function(arg0) { + const ret = getObject(arg0).name; + return addHeapObject(ret); + }; + imports.wbg.__wbg_toString_1c056108b87ba68b = function(arg0) { + const ret = getObject(arg0).toString(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_bedc3d02d0f05eb0 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).set(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isSafeInteger_bb8e18dd21c97288 = function(arg0) { + const ret = Number.isSafeInteger(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_new0_c0be7df4b6bd481f = function() { + const ret = new Date(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_now_9c5990bda04c7e53 = function() { + const ret = Date.now(); + return ret; + }; + imports.wbg.__wbg_toISOString_c588641de3e1665d = function(arg0) { + const ret = getObject(arg0).toISOString(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_entries_e51f29c7bba0c054 = function(arg0) { + const ret = Object.entries(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_is_205d914af04a8faa = function(arg0, arg1) { + const ret = Object.is(getObject(arg0), getObject(arg1)); + return ret; + }; + imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_f7e06ee3c11698eb = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_b2267541e2a73865 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_085ec1f694018c4f = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_6da8e527659b86aa = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_8125e318e6245eed = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_5cf90238115182c3 = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_72e2208bbc0efc61 = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Uint8Array; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_set_092e06b0f9d71865 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) { + const v = getObject(arg1); + const ret = typeof(v) === 'bigint' ? v : undefined; + getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len1; + getInt32Memory0()[arg0 / 4 + 0] = ptr1; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper1151 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 587, __wbg_adapter_48); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper3677 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1715, __wbg_adapter_51); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper3753 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1744, __wbg_adapter_54); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper3837 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 1781, __wbg_adapter_57); + return addHeapObject(ret); + }; + + return imports; +} + +function __wbg_init_memory(imports, maybe_memory) { + +} + +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module; + cachedBigInt64Memory0 = null; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + const imports = __wbg_get_imports(); + + __wbg_init_memory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(input) { + if (wasm !== undefined) return wasm; + + if (typeof input === 'undefined') { + input = new URL('kanidmd_web_ui_user_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + __wbg_init_memory(imports); + + const { instance, module } = await __wbg_load(await input, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync } +export default __wbg_init; diff --git a/server/web_ui/user/pkg/kanidmd_web_ui_user_bg.wasm b/server/web_ui/user/pkg/kanidmd_web_ui_user_bg.wasm new file mode 100644 index 000000000..a6b5c7fd8 Binary files /dev/null and b/server/web_ui/user/pkg/kanidmd_web_ui_user_bg.wasm differ diff --git a/server/web_ui/static/wasmloader.js b/server/web_ui/user/pkg/wasmloader_login_flows.js similarity index 70% rename from server/web_ui/static/wasmloader.js rename to server/web_ui/user/pkg/wasmloader_login_flows.js index 38452d814..1e4d59c8b 100644 --- a/server/web_ui/static/wasmloader.js +++ b/server/web_ui/user/pkg/wasmloader_login_flows.js @@ -1,7 +1,7 @@ // loads the module which loads the WASM. It's loaders all the way down. -import init, { run_app } from '/pkg/kanidmd_web_ui.js'; +import init, { run_app } from '/pkg/kanidmd_web_ui_login_flows.js'; async function main() { - await init('/pkg/kanidmd_web_ui_bg.wasm'); + await init('/pkg/kanidmd_web_ui_login_flows_bg.wasm'); run_app(); } main() diff --git a/server/web_ui/user/pkg/wasmloader_user.js b/server/web_ui/user/pkg/wasmloader_user.js new file mode 100644 index 000000000..3a04a0291 --- /dev/null +++ b/server/web_ui/user/pkg/wasmloader_user.js @@ -0,0 +1,7 @@ +// loads the module which loads the WASM. It's loaders all the way down. +import init, { run_app } from '/pkg/kanidmd_web_ui_user.js'; +async function main() { + await init('/pkg/kanidmd_web_ui_user_bg.wasm'); + run_app(); +} +main() diff --git a/server/web_ui/src/components/change_unix_password.rs b/server/web_ui/user/src/components/change_unix_password.rs similarity index 94% rename from server/web_ui/src/components/change_unix_password.rs rename to server/web_ui/user/src/components/change_unix_password.rs index 54afcc7b5..3ade03166 100644 --- a/server/web_ui/src/components/change_unix_password.rs +++ b/server/web_ui/user/src/components/change_unix_password.rs @@ -1,11 +1,14 @@ use kanidm_proto::v1::{SingleStringRequest, UserAuthToken}; +use kanidmd_web_ui_shared::constants::ID_UNIX_PASSWORDCHANGE; +use kanidmd_web_ui_shared::do_request; +use kanidmd_web_ui_shared::error::FetchError; +use kanidmd_web_ui_shared::RequestMethod; use uuid::Uuid; use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; use web_sys::{FormData, HtmlFormElement}; use yew::prelude::*; -use crate::error::*; -use crate::utils; +use kanidmd_web_ui_shared::utils::{self, modal_hide_by_id}; #[derive(PartialEq)] enum PwCheck { @@ -100,7 +103,7 @@ impl Component for ChangeUnixPassword { } Msg::Success => { self.reset(); - utils::modal_hide_by_id(crate::constants::ID_UNIX_PASSWORDCHANGE); + modal_hide_by_id(ID_UNIX_PASSWORDCHANGE); self.state = State::Init; true } @@ -157,11 +160,11 @@ impl Component for ChangeUnixPassword { -