Started chasing noise, found some code to delete... (#1768)

logging changes:

* Offering auth mechanisms -> debug
* 404's aren't really warnings
* double tombstone message, one goes to debug

other changes:

* CSP changes to allow the bootstrap images to load
* more testing javascriptfile things, I R 
* it's nice to know where things are
* putting non-rust web things in static/ instead of src/
* RequestCredentials::SameOrigin is the default, also adding a utility function to save dupe code. Wow this saved... kilobytes.
* removing commented code, fixing up codespell config
* clippyisms
* wtf, gha
* dee-gloo-ing some things
* adding some ubuntu build test things
* sigh rustwasm/wasm-pack/issues/1138
* more do_request things
* packaging things
* hilarious dev env setup script
* updated script works, all the UI works, including the experimental UI for naughty crabs
* deb package fixes
* fixed some notes
* setup experimental UI tweaks
This commit is contained in:
James Hodgkinson 2023-06-27 11:38:22 +10:00 committed by GitHub
parent 23eb4283e9
commit cc1cc691f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
81 changed files with 891 additions and 974 deletions

View file

@ -1,5 +1,5 @@
---
name: "Build Debian Packages"
name: "Build Deb Packages"
"on":
push:
@ -31,25 +31,33 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
- name: install curl
run: |
apt-get update && \
apt-get install -y \
lsb-release \
libpam0g-dev \
libudev-dev \
libssl-dev \
libsqlite3-dev \
pkg-config \
make \
curl \
sudo
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
apt-get update && apt-get install -y curl
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.3
with:
version: "v0.4.2"
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
scripts/install_ubuntu_dependencies.sh
# apt-get update && \
# apt-get install -y \
# lsb-release \
# libpam0g-dev \
# libudev-dev \
# libssl-dev \
# libsqlite3-dev \
# pkg-config \
# make \
# curl \
# sudo \
# build-essential \
# rsync
- name: Install wasm-pack
run: cargo install wasm-pack
- name: Build packages
run: |
make -f platform/debian/Makefile debs/all

View file

@ -16,21 +16,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
sudo apt-get update &&
sudo apt-get install -y \
libpam0g-dev \
libudev-dev \
libssl-dev \
libsqlite3-dev \
pkg-config
# - name: Check arch
# run: |
# uname -a
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.3
with:
version: "v0.4.2"
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install wasm-pack
run: cargo install wasm-pack
- name: Install dependencies
run: |
scripts/install_ubuntu_dependencies.sh
# https://github.com/browser-actions/setup-chrome
- name: Install Chrome Headless
uses: browser-actions/setup-chrome@latest
@ -45,5 +44,6 @@ jobs:
# docs here:
# https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/browsers.html
- run: make webui
- run: wasm-pack test --headless --chrome
- name: "Run wasm-pack test"
run: make webui/test
continue-on-error: true

14
Cargo.lock generated
View file

@ -1215,6 +1215,7 @@ dependencies = [
"clap",
"clap_complete",
"fs2",
"is-terminal",
"kanidm_lib_file_permissions",
"kanidm_proto",
"kanidmd_core",
@ -2383,6 +2384,18 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -2718,7 +2731,6 @@ version = "1.1.0-beta.13"
dependencies = [
"compact_jwt",
"gloo",
"gloo-net",
"js-sys",
"kanidm_proto",
"qrcode",

View file

@ -122,7 +122,7 @@ codespell:
--skip='./book/book/*' \
--skip='./docs/*,./.git' \
--skip='./rlm_python/mods-available/eap' \
--skip='./server/web_ui/src/external,./server/web_ui/pkg/external' \
--skip='./server/web_ui/static/external,./server/web_ui/pkg/external' \
--skip='./server/lib/src/constants/system_config.rs,./pykanidm/site,./server/lib/src/constants/*.json'
.PHONY: test/pykanidm/pytest
@ -255,3 +255,7 @@ cert/clean:
.PHONY: webui
webui: ## Build the WASM web frontend
cd server/web_ui && ./build_wasm_release.sh
.PHONY: webui/test
webui/test: ## Run wasm-pack test
cd server/web_ui && wasm-pack test --headless --chrome

View file

@ -19,6 +19,8 @@ git and compiler tools. You should install this first.
You will need [rustup](https://rustup.rs/) to install a Rust toolchain.
To build the Web UI you'll need [wasm-pack](https://rustwasm.github.io/wasm-pack/) (`cargo install wasm-pack`).
#### SUSE / OpenSUSE
You will need to install rustup and our build dependencies with:

View file

@ -128,8 +128,8 @@ alias kanidm="docker run ..."
## Initializing the configuration
The client requires a configuration file to connect to the server.
This should be at `/etc/kanidm/config` or `~/.config/kanidm`, and configures the kanidm command line tool.
The client requires a configuration file to connect to the server. This should be at
`/etc/kanidm/config` or `~/.config/kanidm`, and configures the kanidm command line tool.
Here is a minimal example:

View file

@ -1,5 +1,4 @@
# This should be at /etc/kanidm/config or ~/.config/kanidm, and configures the kanidm command line tool
# to point at the local dev server and ignore TLS security.
uri = "https://localhost:8443"
verify_ca = false
verify_hostnames = false
# to point at the local dev server and trust the CA security.
uri="https://localhost:8443"
verify_ca="/tmp/kanidm/ca.pem"

View file

@ -11,8 +11,8 @@ tls_key = "/tmp/kanidm/key.pem"
# NOTE: this is overridden by environment variables at runtime
# Defaults to "info"
#
log_level = "info"
# log_level = "debug"
# log_level = "info"
log_level = "debug"
# log_level = "trace"
domain = "localhost"

View file

@ -3,23 +3,23 @@ name = "kanidm_client"
description = "Kanidm Client Library"
documentation = "https://docs.rs/kanidm_client/latest/kanidm_client/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[dependencies]
tracing.workspace = true
tracing = { workspace = true }
reqwest = { workspace = true, default-features = false }
kanidm_proto.workspace = true
kanidm_proto = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_json = { workspace = true }
time = { workspace = true, features = ["serde", "std"] }
tokio = { workspace = true, features = ["rt", "net", "time", "macros", "sync", "signal"] }
toml.workspace = true
toml = { workspace = true }
uuid = { workspace = true, features = ["serde", "v4"] }
url = { workspace = true, features = ["serde"] }
webauthn-rs-proto = { workspace = true, features = ["wasm"] }

View file

@ -7,20 +7,20 @@ edition = "2021"
tpm = ["dep:tss-esapi"]
[dependencies]
argon2.workspace = true
base64.workspace = true
base64urlsafedata.workspace = true
hex.workspace = true
kanidm_proto.workspace = true
argon2 = { workspace = true }
base64 = { workspace = true }
base64urlsafedata = { workspace = true }
hex = { workspace = true }
kanidm_proto = { workspace = true }
# We need to explicitly ask for openssl-sys so that we get the version propagated
# into the build.rs for legacy feature checks.
openssl-sys.workspace = true
openssl.workspace = true
rand.workspace = true
openssl-sys = { workspace = true }
openssl = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
tracing.workspace = true
tracing = { workspace = true }
tss-esapi = { workspace = true, optional = true }
[dev-dependencies]
sketching.workspace = true
sketching = { workspace = true }

View file

@ -5,13 +5,13 @@ documentation = "https://docs.rs/kanidm/latest/kanidm/"
# We do not have tests in this pkg
autotests = false
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[lib]
name = "profiles"
@ -19,8 +19,8 @@ path = "src/lib.rs"
[dependencies]
serde = { workspace = true, features = ["derive"] }
toml.workspace = true
base64.workspace = true
toml = { workspace = true }
base64 = { workspace = true }
[build-dependencies]
base64.workspace = true
base64 = { workspace = true }

View file

@ -3,18 +3,18 @@ name = "sketching"
# We do not have tests in this pkg
autotests = false
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[dependencies]
async-trait.workspace = true
num_enum.workspace = true
tide.workspace = true
async-trait = { workspace = true }
num_enum = { workspace = true }
tide = { workspace = true }
tracing = { workspace = true, features = ["attributes"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
tracing-forest = { workspace = true, features = ["uuid", "smallvec", "tokio", "env-filter"] }

View file

@ -76,6 +76,12 @@ impl TreeMiddleware {
status = format_args!("{} - {}", status as u16, status.canonical_reason()),
"Client error --> Response sent"
);
} else if status == 404 {
// because not-found isn't really an error, is it?
request_info!(
status = format_args!("{} - {}", status as u16, status.canonical_reason()),
"--> Response sent"
);
} else {
request_warn!(
status = format_args!("{} - {}", status as u16, status.canonical_reason()),

View file

@ -3,31 +3,31 @@ name = "kanidm_proto"
description = "Kanidm Protocol Bindings for serde"
documentation = "https://docs.rs/kanidm_proto/latest/kanidm_proto/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[features]
wasm = ["webauthn-rs-proto/wasm"]
[dependencies]
base32.workspace = true
base64urlsafedata.workspace = true
num_enum.workspace = true
scim_proto.workspace = true
base32 = { workspace = true }
base64urlsafedata = { workspace = true }
num_enum = { workspace = true }
scim_proto = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_json = { workspace = true }
time = { workspace = true, features = ["serde", "std"] }
tracing.workspace = true
tracing = { workspace = true }
url = { workspace = true, features = ["serde"] }
urlencoding.workspace = true
urlencoding = { workspace = true }
uuid = { workspace = true, features = ["serde"] }
webauthn-rs-proto.workspace = true
webauthn-rs-proto = { workspace = true }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
last-git-commit.workspace = true
last-git-commit = { workspace = true }

View file

@ -1099,7 +1099,7 @@ pub struct CUSessionToken {
pub token: String,
}
#[derive(Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CURequest {
PrimaryRemove,

View file

@ -0,0 +1,19 @@
#!/bin/bash
set -e
ERROR=0
if [ -z "$(which cargo)" ]; then
echo "You don't have cargo / rust installed!"
echo "Go to <https://www.rust-lang.org/tools/install> for instructions!"
ERROR=1
fi
if [ -z "$(which wasm-pack)" ]; then
echo "You don't have wasm-pack installed! Installing it now..."
cargo install wasm-pack
fi
if [ $ERROR -eq 1 ]; then
exit 1
fi

View file

@ -0,0 +1,60 @@
#!/bin/bash
set -e
if [ "$(whoami)" == "root" ]; then
SUDOCMD=""
else
SUDOCMD="sudo "
fi
${SUDOCMD} apt-get update &&
${SUDOCMD} apt-get install -y \
libpam0g-dev \
libudev-dev \
libssl-dev \
libsqlite3-dev \
pkg-config \
curl \
rsync \
build-essential
if [ -z "$(which cargo)" ]; then
if [ -f "$HOME/.cargo/env" ]; then
#shellcheck disable=SC1091
source "$HOME/.cargo/env"
elif [ "${INSTALL_RUST}" == "1" ]; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
#shellcheck disable=SC1091
source "$HOME/.cargo/env"
fi
fi
ERROR=0
if [ -z "$(which cargo)" ]; then
echo "You don't have cargo / rust installed!"
echo "Go to <https://www.rust-lang.org/tools/install> for instructions!"
echo ""
echo "Or run this script with INSTALL_RUST=1 to install it for you."
ERROR=1
fi
if [ $ERROR -eq 0 ] && [ -z "$(which wasm-pack)" ]; then
echo "You don't have wasm-pack installed! Installing it now..."
cargo install wasm-pack
fi
if [ $ERROR -eq 0 ] && [ -z "$(which wasm-bindgen)" ]; then
echo "You don't have wasm-bindgen installed! Installing it now..."
cargo install -f wasm-bindgen-cli
fi
if [ $ERROR -eq 1 ]; then
exit 1
fi
echo "Woo, all ready to go!"
#shellcheck disable=SC2016
echo 'You might need to load the env: source "$HOME/.cargo/env"'

125
scripts/setup_dev_environment.sh Executable file
View file

@ -0,0 +1,125 @@
#!/bin/bash
# run this, it'll set up a bunch of default stuff
# - reset the admin and idm_admin users
# - set up a test user
# - set up a test group
# - set up a test oauth2 rp (https://kanidm.com)
# - prompt to reset testuser's creds online
set -e
# if they passed --help then output the help
if [ "${1}" == "--help" ]; then
echo "Usage: $0 [--remove-db]"
echo " --remove-db: remove the existing DB before running"
exit 0
fi
# if --remove-db is in the command line args then remove the DB
if [ -z "${REMOVE_TEST_DB}" ]; then
if [ "${1}" == "--remove-db" ]; then
REMOVE_TEST_DB=1
else
REMOVE_TEST_DB=0
fi
fi
if [ ! -f run_insecure_dev_server.sh ]; then
echo "Please run from the server/daemon dir!"
exit 1
fi
# wait for them to shut down the server if it's running...
while true
do
if [ "$(pgrep kanidmd | wc -l )" -eq 0 ]; then
break
fi
echo "Stop the kanidmd server first please!"
sleep 1
done
# defaults
KANIDM_CONFIG="../../examples/insecure_server.toml"
KANIDM_URL="$(rg origin "${KANIDM_CONFIG}" | awk '{print $NF}' | tr -d '"')"
KANIDM_CA_PATH="/tmp/kanidm/ca.pem"
# needed for the CLI tools to do their thing
export KANIDM_URL
export KANIDM_CA_PATH
export KANIDM_CONFIG
# string things
TEST_USER_NAME="testuser"
TEST_USER_DISPLAY="Test Crab"
TEST_GROUP="test_users"
OAUTH2_RP_ID="test_oauth2"
OAUTH2_RP_DISPLAY="test_oauth2"
# commands to run things
KANIDM="cargo run --manifest-path ../../Cargo.toml --bin kanidm -- "
KANIDMD="cargo run -p daemon --bin kanidmd -- "
if [ "${REMOVE_TEST_DB}" -eq 1 ]; then
echo "Removing the existing DB!"
rm /tmp/kanidm/kanidm.db || true
fi
echo "Reset the admin user"
ADMIN_PASS=$(${KANIDMD} recover-account admin -o json 2>&1 | rg recovery | rg result | jq -r .result )
echo "admin pass: '${ADMIN_PASS}'"
echo "Reset the idm_admin user"
IDM_ADMIN_PASS=$(${KANIDMD} recover-account idm_admin -o json 2>&1 | rg recovery | rg result | jq -r .result)
echo "idm_admin pass: '${IDM_ADMIN_PASS}'"
while true
do
echo "Waiting for you to start the server... testing ${KANIDM_URL}"
curl --cacert "${KANIDM_CA_PATH}" -fs "${KANIDM_URL}" > /dev/null && break
sleep 2
done
echo "login with admin"
${KANIDM} login -D admin --password "${ADMIN_PASS}"
echo "login with idm_admin"
${KANIDM} login -D idm_admin --password "${IDM_ADMIN_PASS}"
# create group test_users
${KANIDM} group create "${TEST_GROUP}" -D idm_admin
# create testuser (person)
${KANIDM} person create "${TEST_USER_NAME}" "${TEST_USER_DISPLAY}" -D idm_admin
echo "Adding ${TEST_USER_NAME} to ${TEST_GROUP}"
${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}"
# create oauth2 rp
echo "Creating the OAuth2 RP"
${KANIDM} system oauth2 create "${OAUTH2_RP_ID}" "${OAUTH2_RP_DISPLAY}" "https://kanidm.com" -D admin
echo "Creating the OAuth2 RP Scope Map"
${KANIDM} system oauth2 update-scope-map "${OAUTH2_RP_ID}" "${TEST_GROUP}" openid -D admin
echo "Creating the 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."
# config auth2
echo "Pulling secret for the OAuth2 RP"
${KANIDM} system oauth2 show-basic-secret -o json "${OAUTH2_RP_ID}" -D admin
echo "Creating cred reset link for ${TEST_USER_NAME}"
${KANIDM} person credential create-reset-token "${TEST_USER_NAME}" -D idm_admin
echo "Done!"
echo "###################################"
echo "admin password: ${ADMIN_PASS}"
echo "idm_admin password: ${IDM_ADMIN_PASS}"
echo "UI URL: ${KANIDM_URL}"
echo "###################################"

View file

@ -38,7 +38,7 @@ tokio-openssl = { workspace = true }
tokio-util = { workspace = true, features = ["codec"] }
toml = {workspace = true}
tracing = { workspace = true, features = ["attributes"] }
urlencoding.workspace = true
urlencoding = { workspace = true }
uuid = { workspace = true, features = ["serde", "v4" ] }
[build-dependencies]

View file

@ -77,7 +77,7 @@ impl ServerConfig {
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default)]
#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq)]
pub enum ServerRole {
#[default]
WriteReplica,

View file

@ -200,6 +200,8 @@ impl<State: Clone + Send + Sync + 'static> tide::Middleware<State>
"base-uri 'self'",
// nobody wants to be in a frame
"frame-ancestors 'none'",
// allow inline images because bootstrap
"img-src 'self' data:",
]
.join(";"),
);

View file

@ -52,16 +52,42 @@ impl JavaScriptFile {
/// returns a `<script>` HTML tag
fn as_tag(self) -> String {
let typeattr = match self.filetype {
Some(val) => format!("type=\"{}\" ", val),
Some(val) => {
format!(" type=\"{}\"", val.as_str())
}
_ => String::from(""),
};
format!(
r#"<script src="/pkg/{}" integrity="{}" {}></script>"#,
self.filepath, self.hash, typeattr,
r#"<script src="/pkg/{}" integrity="{}"{}></script>"#,
self.filepath, &self.hash, &typeattr,
)
}
}
#[test]
fn test_javscriptfile() {
// make sure it outputs what we think it does
use JavaScriptFile;
let jsf = JavaScriptFile {
filepath: "wasmloader.js",
hash: "sha384-1234567890".to_string(),
filetype: Some("module".to_string()),
};
assert_eq!(
jsf.as_tag(),
r#"<script src="/pkg/wasmloader.js" integrity="sha384-1234567890" type="module"></script>"#
);
let jsf = JavaScriptFile {
filepath: "wasmloader.js",
hash: "sha384-1234567890".to_string(),
filetype: None,
};
assert_eq!(
jsf.as_tag(),
r#"<script src="/pkg/wasmloader.js" integrity="sha384-1234567890"></script>"#
);
}
#[derive(Clone)]
pub struct AppState {
pub status_ref: &'static StatusActor,
@ -352,8 +378,7 @@ pub fn generate_integrity_hash(filename: String) -> Result<String, String> {
pub async fn create_https_server(
address: String,
domain: String,
// opt_tls_params: Option<SslAcceptorBuilder>,
domain: &String,
opt_tls_params: Option<&TlsConfiguration>,
role: ServerRole,
trust_x_forward_for: bool,

View file

@ -51,7 +51,7 @@ use tokio::sync::broadcast;
use crate::actors::v1_read::QueryServerReadV1;
use crate::actors::v1_write::QueryServerWriteV1;
use crate::config::Configuration;
use crate::config::{Configuration, ServerRole};
use crate::interval::IntervalActor;
// === internal setup helpers
@ -914,7 +914,7 @@ pub async fn create_server_core(
// ⚠️ only start the sockets and listeners in non-config-test modes.
let h = self::https::create_https_server(
config.address,
config.domain,
&config.domain,
config.tls_config.as_ref(),
config.role,
config.trust_x_forward_for,
@ -927,7 +927,11 @@ pub async fn create_server_core(
)
.await?;
admin_info!("ready to rock! 🪨 ");
if config.role != ServerRole::WriteReplicaNoUI {
admin_info!("ready to rock! 🪨 UI available at: {}", config.origin);
} else {
admin_info!("ready to rock! 🪨");
}
Some(h)
};

View file

@ -3,13 +3,13 @@ name = "daemon"
description = "Kanidm Server Daemon"
documentation = "https://docs.rs/kanidm/latest/kanidm/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -18,27 +18,28 @@ name = "kanidmd"
path = "src/main.rs"
[dependencies]
kanidm_proto.workspace = true
kanidmd_core.workspace = true
kanidm_lib_file_permissions.workspace = true
sketching.workspace = true
fs2.workspace = true
kanidm_proto = { workspace = true }
kanidmd_core = { workspace = true }
kanidm_lib_file_permissions = { workspace = true }
sketching = { workspace = true }
fs2 = { workspace = true }
clap = { workspace = true, features = ["env"] }
reqwest = { workspace = true }
serde = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] }
toml = { workspace = true }
is-terminal = "0.4.7"
[target.'cfg(target_family = "windows")'.dependencies]
whoami.workspace = true
whoami = { workspace = true }
[target.'cfg(not(target_family = "windows"))'.dependencies]
users.workspace = true
tikv-jemallocator.workspace = true
users = { workspace = true }
tikv-jemallocator = { workspace = true }
[build-dependencies]
serde = { workspace = true, features = ["derive"] }
clap = { workspace = true, features = ["derive"] }
clap_complete.workspace = true
profiles.workspace = true
clap_complete = { workspace = true }
profiles = { workspace = true }

View file

@ -126,7 +126,7 @@ async fn main() -> ExitCode {
};
// if they specified it in the environment then that overrides everything
let log_level = match EnvFilter::try_from_default_env() {
let log_filter = match EnvFilter::try_from_default_env() {
Ok(val) => val,
Err(_e) => {
// we couldn't get it from the env, so we'll try the config file!
@ -140,14 +140,25 @@ async fn main() -> ExitCode {
.into()
}
};
// TODO: only send to stderr when we're not in a TTY
tracing_forest::worker_task()
.set_global(true)
.set_tag(sketching::event_tagger)
// Fall back to stderr
.map_sender(|sender| sender.or_stderr())
.build_on(|subscriber| subscriber
.with(log_level)
)
.build_on(|subscriber|{
let sub = subscriber.with(log_filter);
// this does NOT work, it just adds a layer.
// if std::io::stdout().is_terminal() {
// println!("Stdout is a terminal");
// sub.with(sketching::tracing_subscriber::fmt::layer().with_writer(std::io::stderr))
// } else {
// println!("Stdout is not a terminal");
// sub.with(sketching::tracing_subscriber::fmt::layer().with_writer(std::io::stderr))
// }
sub
})
.on(async {
// Get information on the windows username
#[cfg(target_family = "windows")]

View file

@ -7,7 +7,7 @@ edition = "2021"
proc-macro = true
[dependencies]
proc-macro2.workspace = true
quote.workspace = true
syn.workspace = true
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { workspace = true }

View file

@ -3,13 +3,13 @@ name = "kanidmd_lib"
description = "Kanidm Server Backend Library"
documentation = "https://docs.rs/kanidm/latest/kanidm/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[lib]
name = "kanidmd_lib"
@ -20,73 +20,73 @@ name = "scaling_10k"
harness = false
[dependencies]
async-trait.workspace = true
base64.workspace = true
base64urlsafedata.workspace = true
async-trait = { workspace = true }
base64 = { workspace = true }
base64urlsafedata = { workspace = true }
compact_jwt = { workspace = true, features = ["openssl"] }
concread.workspace = true
dyn-clone.workspace = true
concread = { workspace = true }
dyn-clone = { workspace = true }
fernet = { workspace = true, features = ["fernet_danger_timestamps"] }
filetime.workspace = true
futures-util.workspace = true
hashbrown.workspace = true
idlset.workspace = true
kanidm_proto.workspace = true
kanidm_lib_crypto.workspace = true
lazy_static.workspace = true
ldap3_proto.workspace = true
libc.workspace = true
libsqlite3-sys.workspace = true
num_enum.workspace = true
filetime = { workspace = true }
futures-util = { workspace = true }
hashbrown = { workspace = true }
idlset = { workspace = true }
kanidm_proto = { workspace = true }
kanidm_lib_crypto = { workspace = true }
lazy_static = { workspace = true }
ldap3_proto = { workspace = true }
libc = { workspace = true }
libsqlite3-sys = { workspace = true }
num_enum = { workspace = true }
# We need to explicitly ask for openssl-sys so that we get the version propagated
# into the build.rs for legacy feature checks.
openssl-sys.workspace = true
openssl.workspace = true
rand.workspace = true
openssl-sys = { workspace = true }
openssl = { workspace = true }
rand = { workspace = true }
regex = { workspace = true, features = ["std", "perf", "perf-inline", "unicode", "unicode-gencat"] }
serde = { workspace = true, features = ["derive"] }
serde_cbor.workspace = true
serde_json.workspace = true
sketching.workspace = true
serde_cbor = { workspace = true }
serde_json = { workspace = true }
sketching = { workspace = true }
smartstring = { workspace = true, features = ["serde"] }
smolset.workspace = true
sshkeys.workspace = true
tide.workspace = true
smolset = { workspace = true }
sshkeys = { workspace = true }
tide = { workspace = true }
time = { workspace = true, features = ["serde", "std"] }
tokio = { workspace = true, features = ["net", "sync", "time", "rt"] }
tokio-util = { workspace = true, features = ["codec"] }
toml.workspace = true
touch.workspace = true
toml = { workspace = true }
touch = { workspace = true }
nonempty = { workspace = true, features = ["serialize"] }
tracing = { workspace = true, features = ["attributes"] }
url = { workspace = true, features = ["serde"] }
urlencoding.workspace = true
urlencoding = { workspace = true }
uuid = { workspace = true, features = ["serde", "v4" ] }
webauthn-rs = { workspace = true, features = ["resident-key-support", "preview-features", "danger-credential-internals"] }
webauthn-rs-core.workspace = true
zxcvbn.workspace = true
webauthn-rs-core = { workspace = true }
zxcvbn = { workspace = true }
# because windows really can't build without the bundled one
[target.'cfg(target_family = "windows")'.dependencies]
rusqlite = { workspace = true, features = ["bundled"] }
whoami.workspace = true
whoami = { workspace = true }
[target.'cfg(not(target_family = "windows"))'.dependencies]
rusqlite.workspace = true
users.workspace = true
rusqlite = { workspace = true }
users = { workspace = true }
[features]
# default = [ "libsqlite3-sys/bundled", "openssl/vendored" ]
[dev-dependencies]
criterion = { workspace = true, features = ["html_reports"] }
webauthn-authenticator-rs.workspace = true
webauthn-authenticator-rs = { workspace = true }
futures.workspace = true
kanidmd_lib_macros.workspace = true
futures = { workspace = true }
kanidmd_lib_macros = { workspace = true }
[build-dependencies]
profiles.workspace = true
profiles = { workspace = true }

View file

@ -1254,7 +1254,7 @@ impl<'a> BackendWriteTransaction<'a> {
})?;
if entries.is_empty() {
admin_info!("No entries affected - reap_tombstones operation success");
admin_debug!("No entries affected - reap_tombstones operation success");
return Ok(0);
}

View file

@ -815,7 +815,7 @@ impl AuthSession {
// of what's next, or ordering.
let valid_mechs = auth_session.valid_auth_mechs();
security_info!(?valid_mechs, "Offering auth mechanisms");
security_debug!(?valid_mechs, "Offering auth mechanisms");
let as_state = AuthState::Choose(valid_mechs);
(Some(auth_session), as_state)
}

View file

@ -39,7 +39,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
])))?;
if rc.is_empty() {
admin_info!("No recycled present - purge operation success");
admin_info!("No recycled items present - purge operation success");
return Ok(());
}

View file

@ -7,8 +7,8 @@ edition = "2021"
proc-macro = true
[dependencies]
proc-macro2.workspace = true
quote.workspace = true
syn.workspace = true
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { workspace = true }

View file

@ -3,40 +3,40 @@ name = "kanidmd_testkit"
description = "Kanidm Server Test Framework"
documentation = "https://docs.rs/kanidm/latest/kanidm/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[lib]
name = "kanidmd_testkit"
path = "src/lib.rs"
[dependencies]
kanidm_client.workspace = true
kanidm_proto.workspace = true
kanidmd_core.workspace = true
kanidmd_lib.workspace = true
kanidm_client = { workspace = true }
kanidm_proto = { workspace = true }
kanidmd_core = { workspace = true }
kanidmd_lib = { workspace = true }
url = { workspace = true, features = ["serde"] }
reqwest = { workspace = true, default-features = false }
sketching.workspace = true
testkit-macros.workspace = true
sketching = { workspace = true }
testkit-macros = { workspace = true }
tracing = { workspace = true, features = ["attributes"] }
tokio = { workspace = true, features = ["net", "sync", "io-util", "macros"] }
[build-dependencies]
profiles.workspace = true
profiles = { workspace = true }
[dev-dependencies]
compact_jwt.workspace = true
serde_json.workspace = true
webauthn-authenticator-rs.workspace = true
compact_jwt = { workspace = true }
serde_json = { workspace = true }
webauthn-authenticator-rs = { workspace = true }
oauth2_ext = { workspace = true, default-features = false }
futures.workspace = true
time.workspace = true
futures = { workspace = true }
time = { workspace = true }

View file

@ -22,9 +22,6 @@ repository = "https://github.com/kanidm/kanidm/"
# homepage = { workspace = true }
# repository = { workspace = true }
# These are ignored because the crate is in a workspace
#[profile.release]
# less code to include into binary
[lib]
crate-type = ["cdylib", "rlib"]
@ -33,7 +30,6 @@ crate-type = ["cdylib", "rlib"]
compact_jwt = { workspace = true, default-features = false, features = ["unsafe_release_without_verify"] }
# gloo = "^0.8.0"
gloo = { workspace = true }
gloo-net = { workspace = true }
js-sys = { workspace = true }
kanidm_proto = { workspace = true, features = ["wasm"] }
qrcode = { workspace = true, features = ["svg"] }

View file

@ -16,6 +16,11 @@ if [ -z "$(which rsync)" ]; then
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"
rm pkg/kanidmd*
@ -23,13 +28,10 @@ fi
# we can disable this since we want it to expand
# shellcheck disable=SC2086
wasm-pack build ${BUILD_FLAGS} --target web || exit 1
wasm-pack build ${BUILD_FLAGS} --target web --mode no-install --no-pack || exit 1
touch ./pkg/ANYTHING_HERE_WILL_BE_DELETED_ADD_TO_SRC && \
rsync --delete-after -r --copy-links -v ./src/img/ ./pkg/img/ && \
rsync --delete-after -r --copy-links -v ./src/external/ ./pkg/external/ && \
rsync --delete-after -r --copy-links -v ./static/* ./pkg/ && \
cp ../../README.md ./pkg/
cp ../../LICENSE.md ./pkg/
cp ./src/style.css ./pkg/style.css && \
cp ./src/wasmloader.js ./pkg/wasmloader.js && \
rm ./pkg/.gitignore

View file

@ -234,24 +234,24 @@ function addBorrowedObject(obj) {
}
function __wbg_adapter_48(arg0, arg1, arg2) {
try {
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd63bd1cb9b35210b(arg0, arg1, addBorrowedObject(arg2));
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hd11765386bfbbb1b(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__h4a4d23d6ebf5b8fa(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__hf7e9e605a1806538(arg0, arg1, addBorrowedObject(arg2));
wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h13182848512d5ace(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__h9e05cfbc2276f207(arg0, arg1, addHeapObject(arg2));
}
/**
*/
export function run_app() {
@ -330,10 +330,6 @@ async function __wbg_load(module, imports) {
function __wbg_get_imports() {
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === undefined;
return ret;
};
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = typeof(obj) === 'string' ? obj : undefined;
@ -369,6 +365,10 @@ function __wbg_get_imports() {
const ret = getObject(arg0);
return addHeapObject(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;
@ -643,20 +643,6 @@ function __wbg_get_imports() {
imports.wbg.__wbg_remove_8ae45e50cb58bb66 = function() { return handleError(function (arg0, arg1, arg2) {
getObject(arg0).remove(getStringFromWasm0(arg1, arg2));
}, arguments) };
imports.wbg.__wbg_instanceof_WorkerGlobalScope_d9d741da0fb130ce = function(arg0) {
let result;
try {
result = getObject(arg0) instanceof WorkerGlobalScope;
} catch {
result = false;
}
const ret = result;
return ret;
};
imports.wbg.__wbg_fetch_8eaf01857a5bb21f = function(arg0, arg1) {
const ret = getObject(arg0).fetch(getObject(arg1));
return addHeapObject(ret);
};
imports.wbg.__wbg_instanceof_Element_4622f5da1249a3eb = function(arg0) {
let result;
try {
@ -711,10 +697,6 @@ function __wbg_get_imports() {
imports.wbg.__wbg_focus_dbcbbbb2a04c0e1f = function() { return handleError(function (arg0) {
getObject(arg0).focus();
}, arguments) };
imports.wbg.__wbg_new_1eead62f64ca15ce = function() { return handleError(function () {
const ret = new Headers();
return addHeapObject(ret);
}, 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);
@ -725,29 +707,14 @@ function __wbg_get_imports() {
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_url_fda63503ced387ff = function(arg0, arg1) {
const ret = getObject(arg1).url;
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_headers_b439dcff02e808e5 = function(arg0) {
const ret = getObject(arg0).headers;
return addHeapObject(ret);
};
imports.wbg.__wbg_newwithstr_3d9bc779603a93c7 = function() { return handleError(function (arg0, arg1) {
const ret = new Request(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
}, arguments) };
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_new_2a98b9c4a51bdc04 = function() { return handleError(function () {
const ret = new URLSearchParams();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_create_c7e40b6b88186cbf = function() { return handleError(function (arg0, arg1) {
const ret = getObject(arg0).create(getObject(arg1));
return addHeapObject(ret);
@ -782,10 +749,6 @@ function __wbg_get_imports() {
const ret = getObject(arg0).json();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_text_a667ac1770538491 = function() { return handleError(function (arg0) {
const ret = getObject(arg0).text();
return addHeapObject(ret);
}, arguments) };
imports.wbg.__wbg_log_1d3ae0273d8f4f8a = function(arg0) {
console.log(getObject(arg0));
};
@ -1090,10 +1053,6 @@ function __wbg_get_imports() {
const ret = Object.is(getObject(arg0), getObject(arg1));
return ret;
};
imports.wbg.__wbg_toString_a8e343996af880e9 = function(arg0) {
const ret = getObject(arg0).toString();
return addHeapObject(ret);
};
imports.wbg.__wbg_resolve_53698b95aaf7fcf8 = function(arg0) {
const ret = Promise.resolve(getObject(arg0));
return addHeapObject(ret);
@ -1159,16 +1118,16 @@ function __wbg_get_imports() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper4681 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1097, __wbg_adapter_48);
imports.wbg.__wbindgen_closure_wrapper4628 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1074, __wbg_adapter_48);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper5482 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1396, __wbg_adapter_51);
imports.wbg.__wbindgen_closure_wrapper5401 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1357, __wbg_adapter_51);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper5489 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1400, __wbg_adapter_54);
imports.wbg.__wbindgen_closure_wrapper6520 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 1431, __wbg_adapter_54);
return addHeapObject(ret);
};

View file

@ -1,24 +0,0 @@
{
"name": "kanidmd_web_ui",
"collaborators": [
"William Brown <william@blackhats.net.au>",
"James Hodgkinson <james@terminaloutcomes.com>"
],
"description": "Kanidm Server Web User Interface",
"version": "1.1.0-beta.13",
"license": "MPL-2.0",
"repository": {
"type": "git",
"url": "https://github.com/kanidm/kanidm/"
},
"files": [
"kanidmd_web_ui_bg.wasm",
"kanidmd_web_ui.js",
"LICENSE.md"
],
"module": "kanidmd_web_ui.js",
"homepage": "https://github.com/kanidm/kanidm/",
"sideEffects": [
"./snippets/*"
]
}

View file

@ -9,8 +9,9 @@ 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, init_request};
use crate::utils::{do_alert_error, do_page_header};
use crate::views::AdminRoute;
use crate::{do_request, RequestMethod};
impl From<GetError> for AdminListAccountsMsg {
fn from(ge: GetError) -> Self {
@ -93,24 +94,21 @@ pub async fn get_accounts() -> Result<AdminListAccountsMsg, GetError> {
];
for (endpoint, object_type) in endpoints {
let request = init_request(endpoint);
let response = match request.send().await {
Ok(value) => value,
let (_, _, value, _) = match do_request(endpoint, RequestMethod::GET, None).await {
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
}
};
#[allow(clippy::panic)]
let data: Vec<Entity> = match response.json().await {
Ok(value) => value,
// TODO: this kind of thing comes back when you're logged out: SerdeError(Error("invalid type: string \"sessionexpired\", expected a sequence", line: 1, column: 16))', server/web_ui/src/components/admin_accounts.rs:107:27
let data: Vec<Entity> = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => {
return Err(GetError {
err: format!("Failed to grab the account data into JSON: {:?}", error),
})
});
}
};
@ -544,41 +542,59 @@ impl Component for AdminViewServiceAccount {
/// pull the details for a single person by UUID
pub async fn get_person(uuid: &str) -> Result<AdminViewPersonMsg, GetError> {
let request = init_request(format!("/v1/person/{}", uuid).as_str());
let response = match request.send().await {
Ok(value) => value,
let (_, _, value, _) = match do_request(
format!("/v1/person/{}", uuid).as_str(),
RequestMethod::GET,
None,
)
.await
{
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
}
};
#[allow(clippy::panic)]
let data: Entity = match response.json().await {
let data: Entity = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => panic!("Failed to grab the person data into JSON: {:?}", error),
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
});
}
};
Ok(AdminViewPersonMsg::Responded { response: data })
}
/// pull the details for a single service_account by UUID
pub async fn get_service_account(uuid: &str) -> Result<AdminViewServiceAccountMsg, GetError> {
let request = init_request(format!("/v1/service_account/{}", uuid).as_str());
let response = match request.send().await {
let (_, _, value, _) = match do_request(
format!("/v1/service_account/{}", uuid).as_str(),
RequestMethod::GET,
None,
)
.await
{
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!(
"Failed to grab the service_account data into JSON: {:?}",
error
),
})
}
};
let data: Entity = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
});
}
};
#[allow(clippy::panic)]
let data: Entity = match response.json().await {
Ok(value) => value,
Err(error) => panic!(
"Failed to grab the service account data into JSON: {:?}",
error
),
};
Ok(AdminViewServiceAccountMsg::Responded { response: data })
}

View file

@ -7,8 +7,9 @@ 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, init_request};
use crate::utils::{do_alert_error, do_page_header};
use crate::views::AdminRoute;
use crate::{do_request, RequestMethod};
impl From<GetError> for AdminListGroupsMsg {
fn from(ge: GetError) -> Self {
@ -70,20 +71,23 @@ pub async fn get_groups() -> Result<AdminListGroupsMsg, GetError> {
let endpoints = [("/v1/group", EntityType::Group)];
for (endpoint, object_type) in endpoints {
let request = init_request(endpoint);
let response = match request.send().await {
let (_, _, value, _) = match do_request(endpoint, RequestMethod::GET, None).await {
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("Failed to grab the group data into JSON: {:?}", error),
})
}
};
let data: Vec<Entity> = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
});
}
};
#[allow(clippy::panic)]
let data: Vec<Entity> = match response.json().await {
Ok(value) => value,
Err(error) => panic!("Failed to grab the group data into JSON: {:?}", error),
};
for entity in data.iter() {
let mut new_entity = entity.to_owned();
@ -360,19 +364,23 @@ impl Component for AdminViewGroup {
/// pull the details for a single group by UUID
pub async fn get_group(groupid: &str) -> Result<AdminViewGroupMsg, GetError> {
let request = init_request(format!("/v1/group/{}", groupid).as_str());
let response = match request.send().await {
Ok(value) => value,
let endpoint = format!("/v1/group/{}", groupid);
let (_, _, value, _) = match do_request(&endpoint, RequestMethod::GET, None).await {
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
}
};
#[allow(clippy::panic)]
let data: Entity = match response.json().await {
let data: Entity = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => panic!("Failed to grab the group data into JSON: {:?}", error),
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
});
}
};
Ok(AdminViewGroupMsg::Responded { response: data })
}

View file

@ -7,8 +7,9 @@ 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, init_request};
use crate::utils::{do_alert_error, do_page_header};
use crate::views::AdminRoute;
use crate::{do_request, RequestMethod};
impl From<GetError> for AdminListOAuth2Msg {
fn from(ge: GetError) -> Self {
@ -71,22 +72,25 @@ pub async fn get_entities() -> Result<AdminListOAuth2Msg, GetError> {
let endpoints = [("/v1/oauth2", EntityType::OAuth2RP)];
for (endpoint, object_type) in endpoints {
let request = init_request(endpoint);
let response = match request.send().await {
Ok(value) => value,
let (_, _, value, _) = match do_request(endpoint, RequestMethod::GET, None).await {
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
}
};
#[allow(clippy::panic)]
let data: Vec<Entity> = match response.json().await {
let data: Vec<Entity> = match serde_wasm_bindgen::from_value(value) {
Ok(value) => value,
Err(error) => panic!("Failed to grab the OAuth2 RP data into JSON: {:?}", error),
Err(error) => {
return Err(GetError {
err: format!("Failed to grab the oauth2 data into JSON: {:?}", error),
});
}
};
for entity in data.iter() {
for entity in data.into_iter() {
let mut new_entity = entity.to_owned();
new_entity.object_type = object_type.clone();
@ -96,8 +100,9 @@ pub async fn get_entities() -> Result<AdminListOAuth2Msg, GetError> {
.attrs
.uuid
.first()
.expect("Failed to grab the SPN for an account.");
oauth2_objects.insert(entity_id.to_string(), new_entity);
.map(|e| e.to_owned())
.unwrap_or(String::from("Unknown entity name!"));
oauth2_objects.insert(entity_id, new_entity);
}
}
@ -401,17 +406,17 @@ impl Component for AdminViewOAuth2 {
}
pub async fn get_oauth2_rp(rs_name: &str) -> Result<AdminViewOAuth2Msg, GetError> {
let request = init_request(format!("/v1/oauth2/{}", rs_name).as_str());
let response = match request.send().await {
Ok(value) => value,
let endpoint = format!("/v1/oauth2/{}", rs_name);
let (_, _, value, _) = match do_request(&endpoint, RequestMethod::GET, None).await {
Ok(val) => val,
Err(error) => {
return Err(GetError {
err: format!("{:?}", error),
})
}
};
#[allow(clippy::panic)]
let data: Entity = match response.json().await {
let data: Entity = match serde_wasm_bindgen::from_value(value) {
Ok(value) => {
console::log!(format!("{:?}", value));
value

View file

@ -1,8 +1,7 @@
use kanidm_proto::v1::{SingleStringRequest, UserAuthToken};
use uuid::Uuid;
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{FormData, HtmlFormElement, Request, RequestInit, RequestMode, Response};
use web_sys::{FormData, HtmlFormElement};
use yew::prelude::*;
use crate::error::*;
@ -250,32 +249,14 @@ impl ChangeUnixPassword {
})
.map(|s| JsValue::from(&s))
.expect_throw("Failed to change request");
let mut opts = RequestInit::new();
opts.method("PUT");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&changereq_jsvalue));
let uri = format!("/v1/person/{}/_unix/_credential", id);
let request = Request::new_with_str_and_init(uri.as_str(), &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) =
crate::do_request(&uri, crate::RequestMethod::PUT, Some(changereq_jsvalue)).await?;
if status == 200 {
Ok(Msg::Success)
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -10,9 +10,6 @@ use wasm_bindgen::UnwrapThrowExt;
use web_sys::Node;
use crate::error::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestCredentials, RequestInit, RequestMode, Response};
enum State {
Valid,
@ -237,35 +234,17 @@ impl Component for CreateResetCode {
impl CreateResetCode {
async fn credential_get_update_intent_token(id: String) -> Result<Msg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let uri = format!("/v1/person/{}/_credential/_update_intent?ttl=0", id);
let request = Request::new_with_str_and_init(uri.as_str(), &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) =
crate::do_request(&uri, crate::RequestMethod::GET, None).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let token: CUIntentToken =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
Ok(Msg::Ready { token })
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
// let jsval_json = JsFuture::from(resp.json()?).await?;
Ok(Msg::Error { emsg, kopid })
}

View file

@ -1,14 +1,14 @@
#[cfg(debug_assertions)]
use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use yew::prelude::*;
use super::reset::{EventBusMsg, ModalProps};
use crate::do_request;
use crate::error::*;
use crate::utils;
use crate::RequestMethod;
enum State {
Init,
@ -50,37 +50,21 @@ impl DeleteApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
let custatus: CUStatus =
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
cb.emit(EventBusMsg::UpdateStatus { status });
cb.emit(EventBusMsg::UpdateStatus { status: custatus });
Ok(Msg::Success)
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -1,14 +1,13 @@
use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus};
use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use yew::prelude::*;
use super::reset::{EventBusMsg, ModalProps};
use crate::error::*;
use crate::utils;
use crate::{do_request, error::*, RequestMethod};
pub struct PasskeyModalApp {
state: State,
@ -61,30 +60,16 @@ impl PasskeyModalApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
cb.emit(EventBusMsg::UpdateStatus {
status: status.clone(),
@ -102,8 +87,7 @@ impl PasskeyModalApp {
CURegState::None => Msg::Success,
})
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -2,14 +2,13 @@
use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus};
use uuid::Uuid;
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use yew::prelude::*;
use super::reset::{EventBusMsg, PasskeyRemoveModalProps};
use crate::error::*;
use crate::utils;
use crate::{do_request, RequestMethod};
pub struct PasskeyRemoveModalApp {
state: State,
@ -70,30 +69,17 @@ impl PasskeyRemoveModalApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
// this really should require a DELETE not a post!
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
cb.emit(EventBusMsg::UpdateStatus {
status: status.clone(),
@ -111,8 +97,7 @@ impl PasskeyRemoveModalApp {
CURegState::None => Msg::Success,
})
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -1,13 +1,13 @@
use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use yew::prelude::*;
use super::reset::{EventBusMsg, ModalProps};
use crate::error::*;
use crate::utils;
use crate::{do_request, RequestMethod};
enum PwState {
Init,
@ -57,38 +57,24 @@ impl PwModalApp {
}
async fn submit_password_update(token: CUSessionToken, pw: String) -> Result<Msg, FetchError> {
let intentreq_jsvalue = serde_json::to_string(&(CURequest::Password(pw), token))
let req_jsvalue = serde_json::to_string(&(CURequest::Password(pw), token))
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&intentreq_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
Ok(Msg::PasswordResponseSuccess { status })
} else if status == 400 {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let jsval = JsFuture::from(resp.json()?).await?;
let status: OperationError =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
match status {
OperationError::PasswordQuality(feedback) => {
Ok(Msg::PasswordResponseQuality { feedback })
@ -99,9 +85,7 @@ impl PwModalApp {
}),
}
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -3,9 +3,7 @@ use kanidm_proto::v1::{
CUIntentToken, CUSessionToken, CUStatus, CredentialDetail, CredentialDetailType,
};
use uuid::Uuid;
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use yew::prelude::*;
use yew_router::prelude::*;
@ -15,7 +13,7 @@ use super::passkeyremove::PasskeyRemoveModalApp;
use super::pwmodal::PwModalApp;
use super::totpmodal::TotpModalApp;
use super::totpremove::TotpRemoveComp;
use crate::error::*;
use crate::{do_request, error::*, RequestMethod};
use crate::{models, utils};
// use std::rc::Rc;
@ -577,37 +575,23 @@ impl CredentialResetApp {
}
async fn exchange_intent_token(token: String) -> Result<Msg, FetchError> {
let intentreq_jsvalue = serde_json::to_string(&CUIntentToken { token })
let req_jsvalue = serde_json::to_string(&CUIntentToken { token })
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise intent request");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&intentreq_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_exchange_intent", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let (kopid, status, value, _) = do_request(
"/v1/credential/_exchange_intent",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let (token, status): (CUSessionToken, CUStatus) =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
Ok(Msg::BeginSession { token, status })
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}
@ -617,30 +601,13 @@ impl CredentialResetApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise session token");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init(url, &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let (kopid, status, value, _) =
do_request(url, RequestMethod::POST, Some(req_jsvalue)).await?;
if status == 200 {
Ok(Msg::Success)
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -3,14 +3,14 @@ use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret};
use qrcode::render::svg;
use qrcode::QrCode;
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Node, Request, RequestCredentials, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use web_sys::Node;
use yew::prelude::*;
use super::reset::{EventBusMsg, ModalProps};
use crate::error::*;
use crate::utils;
use crate::{do_request, RequestMethod};
enum TotpState {
Init,
@ -74,31 +74,15 @@ impl TotpModalApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
cb.emit(EventBusMsg::UpdateStatus {
status: status.clone(),
@ -115,8 +99,7 @@ impl TotpModalApp {
CURegState::TotpInvalidSha1 => Msg::TotpInvalidSha1,
})
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -2,12 +2,11 @@ use super::reset::{EventBusMsg, TotpRemoveProps};
#[cfg(debug_assertions)]
use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_bindgen::{JsValue, UnwrapThrowExt};
use crate::do_request;
use crate::error::*;
use crate::utils;
use crate::RequestMethod;
use yew::prelude::*;
pub enum Msg {
@ -108,37 +107,21 @@ impl TotpRemoveComp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise pw curequest");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.body(Some(&req_jsvalue));
let request = Request::new_with_str_and_init("/v1/credential/_update", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let (kopid, status, value, _) = do_request(
"/v1/credential/_update",
RequestMethod::POST,
Some(req_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let status: CUStatus =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
cb.emit(EventBusMsg::UpdateStatus { status });
Ok(Msg::Success)
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -11,7 +11,11 @@
#![deny(clippy::needless_pass_by_value)]
#![deny(clippy::trivially_copy_pass_by_ref)]
use error::FetchError;
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;
@ -35,3 +39,57 @@ pub fn run_app() -> Result<(), JsValue> {
gloo::console::debug!(kanidm_proto::utils::get_version("kanidmd_web_ui"));
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<JsValue>,
) -> Result<(Option<String>, 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("content-type", "application/json")
.expect_throw("failed to set 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();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
Ok((kopid, status, JsFuture::from(resp.json()?).await?, headers))
}

View file

@ -6,18 +6,15 @@ use kanidm_proto::v1::{
};
use kanidm_proto::webauthn::PublicKeyCredential;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{spawn_local, JsFuture};
use web_sys::{
CredentialRequestOptions, Request, RequestCredentials, RequestInit, RequestMode, Response,
};
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::{models, utils};
use crate::{do_request, models, utils, RequestMethod};
pub struct LoginApp {
state: LoginState,
@ -105,48 +102,26 @@ impl LoginApp {
issue: AuthIssueSession::Cookie,
},
};
let authreq_jsvalue = serde_json::to_string(&authreq)
let req_jsvalue = serde_json::to_string(&authreq)
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise authreq");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
opts.body(Some(&authreq_jsvalue));
let request = Request::new_with_str_and_init("/v1/auth", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 - auth_init::Response");
let status = resp.status();
let headers = resp.headers();
let (kopid, status, value, _) =
do_request("/v1/auth", RequestMethod::POST, Some(req_jsvalue)).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let state: AuthResponse = serde_wasm_bindgen::from_value(jsval)
let state: AuthResponse = serde_wasm_bindgen::from_value(value)
.expect_throw("Invalid response type - auth_init::AuthResponse");
Ok(LoginAppMsg::Start(state))
} else if status == 404 {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
console::error!(format!(
"User not found: {:?}. Operation ID: {:?}",
text, kopid
value.as_string().unwrap_or_default(),
kopid
));
Ok(LoginAppMsg::UnknownUser)
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(LoginAppMsg::Error { emsg, kopid })
}
}
@ -156,45 +131,23 @@ impl LoginApp {
let authreq_jsvalue = serde_json::to_string(&issue)
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise authreq");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
opts.body(Some(&authreq_jsvalue));
let request = Request::new_with_str_and_init("/v1/reauth", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 - reauth_init::Response");
let status = resp.status();
let headers = resp.headers();
let url = "/v1/reauth";
let (kopid, status, value, _) =
do_request(url, RequestMethod::POST, Some(authreq_jsvalue)).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let state: AuthResponse = serde_wasm_bindgen::from_value(jsval)
let state: AuthResponse = serde_wasm_bindgen::from_value(value)
.expect_throw("Invalid response type - auth_init::AuthResponse");
Ok(LoginAppMsg::Next(state))
} else if status == 404 {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
console::error!(format!(
"User not found: {:?}. Operation ID: {:?}",
text, kopid
value.as_string(),
kopid
));
Ok(LoginAppMsg::UnknownUser)
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(LoginAppMsg::Error { emsg, kopid })
}
}
@ -204,30 +157,11 @@ impl LoginApp {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise authreq");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
opts.body(Some(&authreq_jsvalue));
let request = Request::new_with_str_and_init("/v1/auth", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set content-type 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 - auth_step::Response");
let status = resp.status();
let headers = resp.headers();
let (kopid, status, value, _) =
do_request("/v1/auth", RequestMethod::POST, Some(authreq_jsvalue)).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let state: AuthResponse = serde_wasm_bindgen::from_value(jsval)
let state: AuthResponse = serde_wasm_bindgen::from_value(value)
.map_err(|e| {
console::error!(format!("auth_step::AuthResponse: {:?}", e));
e
@ -235,9 +169,7 @@ impl LoginApp {
.expect_throw("Invalid response type - auth_step::AuthResponse");
Ok(LoginAppMsg::Next(state))
} else {
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string()
let emsg = value.as_string()
.unwrap_or_else(|| "Unhandled error, please report this along with the operation ID below to your administrator. 😔".to_string());
Ok(LoginAppMsg::Error { emsg, kopid })
}
@ -247,6 +179,7 @@ impl LoginApp {
fn button_start_again(&self, ctx: &Context<Self>) -> VNode {
html! {
<div class="col-md-auto text-center">
// TODO: this doesn't seem to work if you failed to login
<button type="button" class={CLASS_BUTTON_DARK} onclick={ ctx.link().callback(|_| LoginAppMsg::Restart) } >{" Start Again "}</button>
</div>
}

View file

@ -1,4 +1,3 @@
// use anyhow::Error;
use gloo::console;
pub use kanidm_proto::oauth2::{
AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, AuthorisationResponse,
@ -6,12 +5,12 @@ pub use kanidm_proto::oauth2::{
};
use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestCredentials, RequestInit, RequestMode, RequestRedirect, Response};
use web_sys::{Request, RequestInit, RequestMode, RequestRedirect, Response};
use yew::prelude::*;
use yew_router::prelude::*;
use crate::error::*;
use crate::manager::Route;
use crate::{do_request, error::*, RequestMethod};
use crate::{models, utils};
use std::collections::BTreeSet;
@ -70,31 +69,15 @@ impl From<FetchError> for Oauth2Msg {
impl Oauth2App {
async fn fetch_session_valid() -> Result<Oauth2Msg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let request = Request::new_with_str_and_init("/v1/auth/valid", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) =
do_request("/v1/auth/valid", RequestMethod::GET, None).await?;
if status == 200 {
Ok(Oauth2Msg::TokenValid)
} else if status == 401 {
Ok(Oauth2Msg::LoginRequired)
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
// let jsval_json = JsFuture::from(resp.json()?).await?;
Ok(Oauth2Msg::Error { emsg, kopid })
}
@ -105,29 +88,15 @@ impl Oauth2App {
.map(|s| JsValue::from(&s))
.expect_throw("Failed to serialise authreq");
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
opts.body(Some(&authreq_jsvalue));
let request = Request::new_with_str_and_init("/oauth2/authorise", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let (kopid, status, value, headers) = do_request(
"/oauth2/authorise",
RequestMethod::POST,
Some(authreq_jsvalue),
)
.await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let state: AuthorisationResponse = serde_wasm_bindgen::from_value(jsval)
let state: AuthorisationResponse = serde_wasm_bindgen::from_value(value)
.map_err(|e| {
let e_msg = format!("serde error -> {:?}", e);
console::error!(e_msg.as_str());
@ -159,8 +128,7 @@ impl Oauth2App {
} else if status == 403 {
Ok(Oauth2Msg::AccessDenied { kopid })
} else {
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Oauth2Msg::Error { emsg, kopid })
}
}
@ -173,8 +141,7 @@ impl Oauth2App {
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::SameOrigin);
opts.redirect(RequestRedirect::Manual);
opts.credentials(RequestCredentials::SameOrigin);
opts.redirect(RequestRedirect::Manual); // can't replace with do_request because of this
opts.body(Some(&consentreq_jsvalue));

View file

@ -1,10 +1,9 @@
use gloo::console;
use gloo_net::http::Request;
use url::Url;
use wasm_bindgen::prelude::*;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
pub use web_sys::InputEvent;
use web_sys::{Document, HtmlElement, HtmlInputElement, RequestCredentials, RequestMode, Window};
use web_sys::{Document, HtmlElement, HtmlInputElement, Window};
use yew::virtual_dom::VNode;
use yew::{html, Html};
@ -94,14 +93,6 @@ pub fn do_footer() -> VNode {
}
}
/// Builds a request object to a server-local endpoint with the usual requirements
pub fn init_request(endpoint: &str) -> gloo_net::http::Request {
Request::new(endpoint)
.mode(RequestMode::SameOrigin)
.credentials(RequestCredentials::SameOrigin)
.header("content-type", "application/json")
}
pub fn do_alert_error(alert_title: &str, alert_message: Option<&str>) -> Html {
html! {
<div class="container">

View file

@ -4,11 +4,8 @@ use yew::prelude::*;
use crate::constants::{CSS_CARD, CSS_LINK_DARK_STRETCHED, CSS_PAGE_HEADER};
use crate::error::FetchError;
use crate::utils;
use crate::{do_request, RequestMethod};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestCredentials, RequestInit, RequestMode, Response};
use kanidm_proto::internal::AppLink;
@ -182,33 +179,15 @@ impl AppsApp {
}
async fn fetch_user_apps() -> Result<Msg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let request = Request::new_with_str_and_init("/v1/self/_applinks", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) =
do_request("/v1/self/_applinks", RequestMethod::GET, None).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let apps: Vec<AppLink> = serde_wasm_bindgen::from_value(jsval)
let apps: Vec<AppLink> = serde_wasm_bindgen::from_value(value)
.expect_throw("Invalid response type - auth_init::AuthResponse");
Ok(Msg::Ready { apps })
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(Msg::Error { emsg, kopid })
}
}

View file

@ -1,16 +1,14 @@
use gloo::console;
use kanidm_proto::v1::{UiHint, UserAuthToken};
use serde::{Deserialize, Serialize};
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestCredentials, RequestInit, RequestMode, Response};
use wasm_bindgen::UnwrapThrowExt;
use yew::prelude::*;
use yew_router::prelude::*;
use crate::components::{admin_accounts, admin_groups, admin_menu, admin_oauth2};
use crate::error::*;
use crate::manager::Route;
use crate::{models, utils};
use crate::models;
use crate::{do_request, error::*, RequestMethod};
mod apps;
mod profile;
@ -328,62 +326,25 @@ impl ViewsApp {
}
async fn check_session_valid() -> Result<ViewsMsg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let request = Request::new_with_str_and_init("/v1/auth/valid", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set header");
let window = utils::window();
let resp_value = JsFuture::from(window.fetch_with_request(&request))
.await
.map_err(|e| {
console::error!(&format!("fetch request failed {:?}", e));
e
})?;
let resp: Response = resp_value.dyn_into().expect_throw("Invalid response type");
let status = resp.status();
let (kopid, status, value, _) =
do_request("/v1/auth/valid", RequestMethod::GET, None).await?;
if status == 200 {
Ok(ViewsMsg::Verified)
} else if status == 401 {
Ok(ViewsMsg::LogoutComplete)
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(ViewsMsg::Error { emsg, kopid })
}
}
async fn fetch_user_data() -> Result<ViewsMsg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let request = Request::new_with_str_and_init("/v1/self/_uat", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) =
do_request("/v1/self/_uat", RequestMethod::GET, None).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let uat: UserAuthToken = serde_wasm_bindgen::from_value(jsval)
let uat: UserAuthToken = serde_wasm_bindgen::from_value(value)
.map_err(|e| {
let e_msg = format!("serde error -> {:?}", e);
console::error!(e_msg.as_str());
@ -392,39 +353,18 @@ impl ViewsApp {
Ok(ViewsMsg::ProfileInfoReceived { uat })
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(ViewsMsg::Error { emsg, kopid })
}
}
async fn fetch_logout() -> Result<ViewsMsg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let request = Request::new_with_str_and_init("/v1/logout", &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _) = do_request("/v1/logout", RequestMethod::GET, None).await?;
if status == 200 {
Ok(ViewsMsg::LogoutComplete)
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
Ok(ViewsMsg::Error { emsg, kopid })
}
}

View file

@ -2,9 +2,7 @@
use gloo::console;
use kanidm_proto::v1::{CUSessionToken, CUStatus, UiHint, UserAuthToken};
use time::format_description::well_known::Rfc3339;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use wasm_bindgen_futures::JsFuture;
use web_sys::{Request, RequestCredentials, RequestInit, RequestMode, Response};
use wasm_bindgen::UnwrapThrowExt;
use yew::prelude::*;
use yew_router::prelude::*;
@ -13,8 +11,8 @@ use crate::components::create_reset_code::CreateResetCode;
use crate::constants::CSS_PAGE_HEADER;
use crate::error::*;
use crate::manager::Route;
use crate::models;
use crate::views::{ViewProps, ViewRoute};
use crate::{models, utils};
#[allow(clippy::large_enum_variant)]
// Page state
@ -240,35 +238,16 @@ impl ProfileApp {
}
async fn request_credential_update(id: String) -> Result<Msg, FetchError> {
let mut opts = RequestInit::new();
opts.method("GET");
opts.mode(RequestMode::SameOrigin);
opts.credentials(RequestCredentials::SameOrigin);
let uri = format!("/v1/person/{}/_credential/_update", id);
let request = Request::new_with_str_and_init(uri.as_str(), &opts)?;
request
.headers()
.set("content-type", "application/json")
.expect_throw("failed to set 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 (kopid, status, value, _headers) =
crate::do_request(&uri, crate::RequestMethod::GET, None).await?;
if status == 200 {
let jsval = JsFuture::from(resp.json()?).await?;
let (token, status): (CUSessionToken, CUStatus) =
serde_wasm_bindgen::from_value(jsval).expect_throw("Invalid response type");
serde_wasm_bindgen::from_value(value).expect_throw("Invalid response type");
Ok(Msg::BeginCredentialUpdate { token, status })
} else {
let headers = resp.headers();
let kopid = headers.get("x-kanidm-opid").ok().flatten();
let text = JsFuture::from(resp.text()?).await?;
let emsg = text.as_string().unwrap_or_default();
let emsg = value.as_string().unwrap_or_default();
// let jsval_json = JsFuture::from(resp.json()?).await?;
Ok(Msg::Error { emsg, kopid })
}

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View file

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View file

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -3,39 +3,39 @@ name = "kanidm-ipa-sync"
description = "Kanidm Client Tools"
documentation = "https://kanidm.github.io/kanidm/stable/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[dependencies]
base64urlsafedata.workspace = true
base64urlsafedata = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
chrono.workspace = true
cron.workspace = true
kanidm_client.workspace = true
kanidm_proto.workspace = true
chrono = { workspace = true }
cron = { workspace = true }
kanidm_client = { workspace = true }
kanidm_proto = { workspace = true }
tokio = { workspace = true, features = ["rt", "macros", "net"] }
tracing.workspace = true
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
ldap3_client.workspace = true
ldap3_client = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
toml.workspace = true
serde_json = { workspace = true }
toml = { workspace = true }
url = { workspace = true, features = ["serde"] }
uuid = { workspace = true, features = ["serde"] }
# For file metadata, should this me moved out?
kanidmd_lib.workspace = true
kanidmd_lib = { workspace = true }
[target.'cfg(target_family = "unix")'.dependencies]
users.workspace = true
users = { workspace = true }
[build-dependencies]
clap = { workspace = true, features = ["derive"] }
clap_complete.workspace = true
clap_complete = { workspace = true }

View file

@ -3,39 +3,39 @@ name = "kanidm-ldap-sync"
description = "Kanidm Client Tools"
documentation = "https://kanidm.github.io/kanidm/stable/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[dependencies]
base64urlsafedata.workspace = true
base64urlsafedata = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
chrono.workspace = true
cron.workspace = true
kanidm_client.workspace = true
kanidm_proto.workspace = true
chrono = { workspace = true }
cron = { workspace = true }
kanidm_client = { workspace = true }
kanidm_proto = { workspace = true }
tokio = { workspace = true, features = ["rt", "macros", "net"] }
tracing.workspace = true
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
ldap3_client.workspace = true
ldap3_client = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
toml.workspace = true
serde_json = { workspace = true }
toml = { workspace = true }
url = { workspace = true, features = ["serde"] }
uuid = { workspace = true, features = ["serde"] }
# For file metadata, should this me moved out?
kanidmd_lib.workspace = true
kanidmd_lib = { workspace = true }
[target.'cfg(target_family = "unix")'.dependencies]
users.workspace = true
users = { workspace = true }
[build-dependencies]
clap = { workspace = true, features = ["derive"] }
clap_complete.workspace = true
clap_complete = { workspace = true }

View file

@ -3,42 +3,42 @@ name = "orca"
description = "Orca - load testing for LDAP and Kanidm"
documentation = "https://docs.rs/kanidm/latest/kanidm/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[[bin]]
name = "orca"
path = "src/main.rs"
[dependencies]
clap.workspace = true
crossbeam.workspace = true
csv.workspace = true
dialoguer.workspace = true
clap = { workspace = true }
crossbeam = { workspace = true }
csv = { workspace = true }
dialoguer = { workspace = true }
futures-util = { workspace = true, features = ["sink"] }
kanidm_client.workspace = true
kanidm_proto.workspace = true
ldap3_proto.workspace = true
mathru.workspace = true
openssl.workspace = true
rand.workspace = true
kanidm_client = { workspace = true }
kanidm_proto = { workspace = true }
ldap3_proto = { workspace = true }
mathru = { workspace = true }
openssl = { workspace = true }
rand = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_json = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread"] }
tokio-openssl.workspace = true
tokio-openssl = { workspace = true }
tokio-util = { workspace = true, features = ["codec"] }
toml.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
toml = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
uuid = { workspace = true, features = ["serde", "v4" ] }
[target.'cfg(not(target_family = "windows"))'.dependencies]
tikv-jemallocator.workspace = true
tikv-jemallocator = { workspace = true }
[build-dependencies]
profiles.workspace = true
profiles = { workspace = true }

View file

@ -3,13 +3,13 @@ name = "kanidm_unix_int"
description = "Kanidm Unix Integration Clients"
documentation = "https://docs.rs/kanidm/latest/kanidm/"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[features]
default = ["unix"]
@ -42,40 +42,40 @@ name = "kanidm_unix_common"
path = "src/lib.rs"
[dependencies]
bytes.workspace = true
bytes = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
csv.workspace = true
futures.workspace = true
libc.workspace = true
libsqlite3-sys.workspace = true
lru.workspace = true
kanidm_client.workspace = true
kanidm_proto.workspace = true
kanidm_lib_crypto.workspace = true
kanidm_lib_file_permissions.workspace = true
notify-debouncer-full.workspace = true
rpassword.workspace = true
rusqlite.workspace = true
csv = { workspace = true }
futures = { workspace = true }
libc = { workspace = true }
libsqlite3-sys = { workspace = true }
lru = { workspace = true }
kanidm_client = { workspace = true }
kanidm_proto = { workspace = true }
kanidm_lib_crypto = { workspace = true }
kanidm_lib_file_permissions = { workspace = true }
notify-debouncer-full = { workspace = true }
rpassword = { workspace = true }
rusqlite = { workspace = true }
selinux = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
sketching.workspace = true
serde_json = { workspace = true }
sketching = { workspace = true }
toml.workspace = true
toml = { workspace = true }
tokio = { workspace = true, features = ["rt", "fs", "macros", "sync", "time", "net", "io-util"] }
tokio-util = { workspace = true, features = ["codec"] }
tracing.workspace = true
tracing = { workspace = true }
tss-esapi = { workspace = true, optional = true }
reqwest = { workspace = true, default-features = false }
walkdir.workspace = true
walkdir = { workspace = true }
[target.'cfg(not(target_family = "windows"))'.dependencies]
users.workspace = true
users = { workspace = true }
[dev-dependencies]
kanidmd_core.workspace = true
kanidmd_core = { workspace = true }
[build-dependencies]
clap = { workspace = true, features = ["derive"] }
clap_complete.workspace = true
profiles.workspace = true
clap_complete = { workspace = true }
profiles = { workspace = true }

View file

@ -2,13 +2,13 @@
name = "pam_kanidm"
links = "pam"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
version = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
homepage = { workspace = true }
repository = { workspace = true }
[lib]
name = "pam_kanidm"
@ -16,8 +16,8 @@ crate-type = [ "cdylib" ]
path = "src/lib.rs"
[dependencies]
kanidm_unix_int.workspace = true
libc.workspace = true
kanidm_unix_int = { workspace = true }
libc = { workspace = true }
[build-dependencies]
pkg-config.workspace = true
pkg-config = { workspace = true }