From 821b2c05c4e3ad34c3d03561fb00b2720f6fbcbe Mon Sep 17 00:00:00 2001 From: Firstyear Date: Sat, 1 Oct 2022 16:08:51 +1000 Subject: [PATCH] Rework deps (#1079) --- .rustfmt.toml | 11 + Cargo.lock | 255 +- Cargo.toml | 122 +- kanidm_client/Cargo.toml | 35 +- kanidm_client/src/lib.rs | 25 +- kanidm_client/src/person.rs | 10 +- kanidm_client/src/service_account.rs | 10 +- kanidm_proto/Cargo.toml | 34 +- kanidm_proto/src/messages.rs | 19 +- kanidm_proto/src/oauth2.rs | 3 +- kanidm_proto/src/v1.rs | 9 +- kanidm_tools/Cargo.toml | 59 +- kanidm_tools/build.rs | 2 +- kanidm_tools/src/badlist_preprocess.rs | 3 +- kanidm_tools/src/cli/common.rs | 11 +- kanidm_tools/src/cli/lib.rs | 1 + kanidm_tools/src/cli/main.rs | 3 +- kanidm_tools/src/cli/person.rs | 23 +- kanidm_tools/src/cli/raw.rs | 6 +- kanidm_tools/src/cli/serviceaccount.rs | 5 +- kanidm_tools/src/cli/session.rs | 27 +- kanidm_tools/src/ssh_authorizedkeys.rs | 1 - kanidm_unix_int/Cargo.toml | 75 +- kanidm_unix_int/build.rs | 3 +- kanidm_unix_int/nss_kanidm/Cargo.toml | 22 +- kanidm_unix_int/nss_kanidm/src/lib.rs | 1 - kanidm_unix_int/pam_kanidm/Cargo.toml | 18 +- kanidm_unix_int/pam_kanidm/src/lib.rs | 9 +- kanidm_unix_int/pam_kanidm/src/pam/conv.rs | 6 +- kanidm_unix_int/pam_kanidm/src/pam/macros.rs | 24 +- kanidm_unix_int/pam_kanidm/src/pam/module.rs | 3 +- kanidm_unix_int/pam_tester/Cargo.toml | 13 +- kanidm_unix_int/src/cache.rs | 17 +- kanidm_unix_int/src/cache_clear.rs | 2 - kanidm_unix_int/src/cache_invalidate.rs | 2 - kanidm_unix_int/src/client.rs | 11 +- kanidm_unix_int/src/client_sync.rs | 5 +- kanidm_unix_int/src/daemon.rs | 32 +- kanidm_unix_int/src/daemon_status.rs | 4 +- kanidm_unix_int/src/db.rs | 17 +- kanidm_unix_int/src/ssh_authorizedkeys.rs | 3 +- kanidm_unix_int/src/tasks_daemon.rs | 30 +- kanidm_unix_int/src/test_auth.rs | 2 - kanidm_unix_int/src/unix_config.rs | 14 +- kanidm_unix_int/tests/cache_layer_test.rs | 12 +- kanidmd/daemon/Cargo.toml | 45 +- kanidmd/daemon/build.rs | 1 - kanidmd/daemon/src/main.rs | 26 +- kanidmd/idm/Cargo.toml | 133 +- kanidmd/idm/benches/scaling_10k.rs | 7 +- kanidmd/idm/src/access.rs | 1100 ++++---- kanidmd/idm/src/actors/v1_read.rs | 1346 +++++----- kanidmd/idm/src/actors/v1_write.rs | 1280 +++++----- kanidmd/idm/src/audit.rs | 3 +- kanidmd/idm/src/be/dbentry.rs | 10 +- kanidmd/idm/src/be/dbvalue.rs | 16 +- kanidmd/idm/src/be/idl_arc_sqlite.rs | 491 ++-- kanidmd/idm/src/be/idl_sqlite.rs | 299 +-- kanidmd/idm/src/be/idxkey.rs | 6 +- kanidmd/idm/src/be/mod.rs | 645 +++-- kanidmd/idm/src/config.rs | 5 +- kanidmd/idm/src/credential/mod.rs | 23 +- kanidmd/idm/src/credential/policy.rs | 3 +- kanidmd/idm/src/credential/totp.rs | 14 +- kanidmd/idm/src/crypto.rs | 3 +- kanidmd/idm/src/entry.rs | 91 +- kanidmd/idm/src/event.rs | 33 +- kanidmd/idm/src/filter.rs | 86 +- kanidmd/idm/src/identity.rs | 6 +- kanidmd/idm/src/idm/account.rs | 54 +- kanidmd/idm/src/idm/authsession.rs | 64 +- kanidmd/idm/src/idm/credupdatesession.rs | 214 +- kanidmd/idm/src/idm/event.rs | 3 +- kanidmd/idm/src/idm/group.rs | 7 +- kanidmd/idm/src/idm/mod.rs | 4 +- kanidmd/idm/src/idm/oauth2.rs | 63 +- kanidmd/idm/src/idm/radius.rs | 13 +- kanidmd/idm/src/idm/server.rs | 238 +- kanidmd/idm/src/idm/serviceaccount.rs | 36 +- kanidmd/idm/src/idm/unix.rs | 22 +- kanidmd/idm/src/interval.rs | 16 +- kanidmd/idm/src/ldap.rs | 173 +- kanidmd/idm/src/lib.rs | 25 +- kanidmd/idm/src/macros.rs | 178 +- kanidmd/idm/src/modify.rs | 20 +- kanidmd/idm/src/plugins/attrunique.rs | 12 +- kanidmd/idm/src/plugins/base.rs | 17 +- kanidmd/idm/src/plugins/domain.rs | 9 +- kanidmd/idm/src/plugins/dyngroup.rs | 11 +- kanidmd/idm/src/plugins/gidnumber.rs | 3 +- kanidmd/idm/src/plugins/jwskeygen.rs | 3 +- kanidmd/idm/src/plugins/memberof.rs | 11 +- kanidmd/idm/src/plugins/mod.rs | 96 +- kanidmd/idm/src/plugins/password_import.rs | 8 +- kanidmd/idm/src/plugins/protected.rs | 6 +- kanidmd/idm/src/plugins/refint.rs | 15 +- kanidmd/idm/src/plugins/spn.rs | 13 +- kanidmd/idm/src/repl/cid.rs | 9 +- kanidmd/idm/src/repl/entry.rs | 20 +- kanidmd/idm/src/repl/ruv.rs | 12 +- kanidmd/idm/src/schema.rs | 1546 +++++------ kanidmd/idm/src/server.rs | 2263 ++++++++--------- kanidmd/idm/src/status.rs | 3 +- kanidmd/idm/src/utils.rs | 27 +- kanidmd/idm/src/value.rs | 25 +- kanidmd/idm/src/valueset/address.rs | 10 +- kanidmd/idm/src/valueset/binary.rs | 12 +- kanidmd/idm/src/valueset/bool.rs | 6 +- kanidmd/idm/src/valueset/cid.rs | 7 +- kanidmd/idm/src/valueset/cred.rs | 13 +- kanidmd/idm/src/valueset/datetime.rs | 8 +- kanidmd/idm/src/valueset/iname.rs | 7 +- kanidmd/idm/src/valueset/index.rs | 6 +- kanidmd/idm/src/valueset/iutf8.rs | 7 +- kanidmd/idm/src/valueset/json.rs | 8 +- kanidmd/idm/src/valueset/jws.rs | 9 +- kanidmd/idm/src/valueset/mod.rs | 37 +- kanidmd/idm/src/valueset/nsuniqueid.rs | 6 +- kanidmd/idm/src/valueset/oauth.rs | 14 +- kanidmd/idm/src/valueset/restricted.rs | 6 +- kanidmd/idm/src/valueset/secret.rs | 6 +- kanidmd/idm/src/valueset/session.rs | 13 +- kanidmd/idm/src/valueset/spn.rs | 7 +- kanidmd/idm/src/valueset/ssh.rs | 7 +- kanidmd/idm/src/valueset/syntax.rs | 6 +- kanidmd/idm/src/valueset/uint32.rs | 6 +- kanidmd/idm/src/valueset/url.rs | 6 +- kanidmd/idm/src/valueset/utf8.rs | 6 +- kanidmd/idm/src/valueset/uuid.rs | 9 +- kanidmd/score/Cargo.toml | 72 +- kanidmd/score/src/https/manifest.rs | 3 +- kanidmd/score/src/https/middleware.rs | 3 +- kanidmd/score/src/https/mod.rs | 17 +- kanidmd/score/src/https/oauth2.rs | 5 +- kanidmd/score/src/https/routemaps.rs | 11 +- kanidmd/score/src/https/v1.rs | 18 +- kanidmd/score/src/ldaps.rs | 19 +- kanidmd/score/src/lib.rs | 11 +- kanidmd/score/tests/https_middleware.rs | 4 +- kanidmd/score/tests/oauth2_test.rs | 9 +- kanidmd/score/tests/proto_v1_test.rs | 11 +- kanidmd_web_ui/Cargo.toml | 54 +- kanidmd_web_ui/pkg/kanidmd_web_ui.js | 1093 -------- kanidmd_web_ui/pkg/kanidmd_web_ui_bg.wasm | Bin 1599068 -> 0 bytes .../src/components/admin_accounts.rs | 11 +- kanidmd_web_ui/src/components/admin_groups.rs | 14 +- kanidmd_web_ui/src/components/admin_oauth2.rs | 13 +- kanidmd_web_ui/src/components/adminmenu.rs | 9 +- .../src/components/change_unix_password.rs | 9 +- kanidmd_web_ui/src/credential/delete.rs | 17 +- kanidmd_web_ui/src/credential/eventbus.rs | 9 +- kanidmd_web_ui/src/credential/passkey.rs | 19 +- .../src/credential/passkeyremove.rs | 20 +- kanidmd_web_ui/src/credential/pwmodal.rs | 17 +- kanidmd_web_ui/src/credential/reset.rs | 17 +- kanidmd_web_ui/src/credential/totpmodal.rs | 23 +- kanidmd_web_ui/src/error.rs | 1 + kanidmd_web_ui/src/login.rs | 12 +- kanidmd_web_ui/src/manager.rs | 2 +- kanidmd_web_ui/src/models/mod.rs | 14 +- kanidmd_web_ui/src/oauth2.rs | 16 +- kanidmd_web_ui/src/views/apps.rs | 5 +- kanidmd_web_ui/src/views/mod.rs | 14 +- kanidmd_web_ui/src/views/profile.rs | 6 +- kanidmd_web_ui/src/views/security.rs | 23 +- orca/Cargo.toml | 60 +- orca/src/data.rs | 2 +- orca/src/ds.rs | 10 +- orca/src/kani.rs | 12 +- orca/src/ldap.rs | 7 +- orca/src/main.rs | 8 +- orca/src/preprocess.rs | 10 +- orca/src/runner/mod.rs | 8 +- orca/src/runner/search.rs | 18 +- orca/src/setup.rs | 14 +- profiles/Cargo.toml | 23 +- profiles/build.rs | 3 +- profiles/src/lib.rs | 3 +- sketching/Cargo.toml | 25 +- sketching/src/lib.rs | 7 +- sketching/src/middleware.rs | 3 +- 181 files changed, 6355 insertions(+), 7591 deletions(-) create mode 100644 .rustfmt.toml delete mode 100644 kanidmd_web_ui/pkg/kanidmd_web_ui.js delete mode 100644 kanidmd_web_ui/pkg/kanidmd_web_ui_bg.wasm diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 000000000..b9129e6f1 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,11 @@ + +reorder_imports = true + +## Requires nightly +# imports_granularity = "Module" +# group_imports = "StdExternalCrate" +# format_code_in_doc_comments = true +# format_macro_bodies = true +# reorder_impl_items = true + + diff --git a/Cargo.lock b/Cargo.lock index 1ae114a29..6b6ef4b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -186,6 +201,7 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345fd392ab01f746c717b1357165b76f0b67a60192007b234058c9045fdcf695" dependencies = [ + "brotli", "flate2", "futures-core", "futures-io", @@ -578,6 +594,27 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bstr" version = "0.2.17" @@ -602,6 +639,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytemuck" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" + [[package]] name = "byteorder" version = "1.4.3" @@ -753,6 +796,12 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "compact_jwt" version = "0.2.8" @@ -850,9 +899,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" dependencies = [ "percent-encoding", "time 0.3.14", @@ -865,7 +914,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" dependencies = [ - "cookie 0.16.0", + "cookie 0.16.1", "idna 0.2.3", "log", "publicsuffix", @@ -1991,6 +2040,19 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2061,6 +2123,20 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "indexmap" version = "1.9.1" @@ -2174,7 +2250,7 @@ dependencies = [ "rusqlite", "saffron", "serde", - "serde_cbor", + "serde_cbor_2", "serde_json", "sketching", "smartstring", @@ -2664,6 +2740,28 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -2724,6 +2822,7 @@ dependencies = [ "getrandom 0.2.7", "http", "rand 0.8.5", + "reqwest", "serde", "serde_json", "serde_path_to_error", @@ -2773,9 +2872,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.41" +version = "0.10.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -2805,9 +2904,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.75" +version = "0.9.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" dependencies = [ "autocfg", "cc", @@ -2919,6 +3018,24 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "phf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +dependencies = [ + "siphasher", +] + [[package]] name = "phonenumber" version = "0.3.1+8.12.9" @@ -3085,9 +3202,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] @@ -3124,6 +3241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" dependencies = [ "checked_int_cast", + "image", ] [[package]] @@ -3341,7 +3459,7 @@ checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64 0.13.0", "bytes", - "cookie 0.16.0", + "cookie 0.16.1", "cookie_store", "encoding_rs", "futures-core", @@ -3350,6 +3468,7 @@ dependencies = [ "http", "http-body", "hyper", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -3360,19 +3479,38 @@ dependencies = [ "percent-encoding", "pin-project-lite 0.2.9", "proc-macro-hack", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "route-recognizer" version = "0.2.0" @@ -3443,6 +3581,27 @@ dependencies = [ "nom 7.1.1", ] +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64 0.13.0", +] + [[package]] name = "ryu" version = "1.0.11" @@ -3511,7 +3670,6 @@ version = "1.1.0-alpha.9" dependencies = [ "async-std", "async-trait", - "base64 0.13.0", "compact_jwt", "futures", "futures-util", @@ -3541,6 +3699,16 @@ dependencies = [ "webauthn-authenticator-rs", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.7.0" @@ -3800,9 +3968,15 @@ dependencies = [ "event-listener", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "sketching" -version = "0.1.0" +version = "1.1.0-alpha.9" dependencies = [ "async-trait", "num_enum", @@ -3861,6 +4035,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "sptr" version = "0.3.2" @@ -3965,9 +4145,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -4027,18 +4207,18 @@ checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" [[package]] name = "thiserror" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85" +checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783" +checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43" dependencies = [ "proc-macro2", "quote", @@ -4086,6 +4266,7 @@ dependencies = [ "async-compression", "futures-lite", "http-types", + "phf", "regex", "tide", ] @@ -4273,6 +4454,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + [[package]] name = "tokio-util" version = "0.7.4" @@ -4441,6 +4633,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.3.1" @@ -4774,6 +4972,25 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" +dependencies = [ + "webpki", +] + [[package]] name = "wepoll-ffi" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index f92ce1de4..93c34448b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,20 +17,131 @@ members = [ "kanidmd/score", "orca", "profiles", - "sketching", + "sketching" ] exclude = [ "kanidm_unix_int/pam_tester" ] +[workspace.package] +version = "1.1.0-alpha.9" +authors = [ + "William Brown ", + "James Hodgkinson ", + ] +rust-version = "1.64" +edition = "2021" +license = "MPL-2.0" +homepage = "https://github.com/kanidm/kanidm/" +repository = "https://github.com/kanidm/kanidm/" [workspace.dependencies] +async-std = { version = "^1.12.0", features = ["tokio1"] } +async-trait = "^0.1.57" +base32 = "^0.4.0" +base64 = "^0.13.0" +base64urlsafedata = "0.1.0" +bytes = "^1.1.0" +clap = { version = "^3.2", features = ["derive"] } +clap_complete = "^3.2.5" +# Forced by saffron +chrono = "^0.4.20" +compact_jwt = "^0.2.3" # compact_jwt = { path = "../compact_jwt" } +concread = "^0.4.0" # concread = { path = "../concread" } +crossbeam = "0.8.1" +criterion = "^0.4.0" +csv = "1.1.6" +dialoguer = "0.10.1" +dyn-clone = "^1.0.9" +fernet = "^0.2.0" +filetime = "^0.2.17" +futures = "^0.3.21" +futures-util = "^0.3.21" +gloo = "^0.8.0" +gloo-net = "0.2.4" +hashbrown = { version = "0.12.3", features = ["serde", "inline-more", "ahash"] } +http-types = "^2.12.0" +idlset = "^0.2.4" # idlset = { path = "../idlset" } -# ldap3_server = { path = "../ldap3_server" } +js-sys = "^0.3.58" +# RENAME THIS +kanidm = { path = "./kanidmd/idm" } +kanidm_client = { path = "./kanidm_client" } +kanidm_proto = { path = "./kanidm_proto" } +kanidm_unix_int = { path = "./kanidm_unix_int" } +last-git-commit = "0.2.0" +# REMOVE this +lazy_static = "^1.4.0" +ldap3_proto = "^0.2.3" +libc = "^0.2.127" +libnss = "^0.4.0" +libsqlite3-sys = "^0.25.0" +lru = "^0.8.0" +mathru = "^0.13.0" +num_enum = "^0.5.7" +oauth2_ext = { version = "^4.1.0", package = "oauth2" } +openssl = "^0.10.41" +paste = "^1.0.9" +pkg-config = "^0.3.25" +profiles = { path = "./profiles" } +qrcode = "^0.12.0" +r2d2 = "^0.8.9" +r2d2_sqlite = "^0.21.0" +rand = "^0.8.5" +# try to remove this +rayon = "^1.5.3" +regex = "1.5.6" +reqwest = "0.11.11" +rpassword = "^7.0.0" +rusqlite = "^0.28.0" +saffron = "^0.1.0" +# Rename this! +score = { path = "./kanidmd/score" } +serde = "^1.0.142" +serde_cbor = { version = "0.12.0-dev", package = "serde_cbor_2" } +serde_json = "^1.0.83" +serde-wasm-bindgen = "0.4" +shellexpand = "^2.1.2" +sketching = { path = "./sketching" } +smartstring = "^1.0.1" +smolset = "^1.3.1" +sshkeys = "^0.3.1" +tide = "^0.16.0" +tide-compress = "0.10.6" +tide-openssl = "^0.1.1" + +# Unable to increase version due to removing ability to detect +# local platform time. +time = "=0.2.27" + +tikv-jemallocator = "0.5" + +tokio = "^1.21.1" +tokio-openssl = "^0.6.3" +tokio-util = "^0.7.4" + +toml = "^0.5.9" +touch = "^0.0.1" +tracing = { version = "^0.1.35", features = ["max_level_trace", "release_max_level_debug"] } +tracing-subscriber = { version = "^0.3.14", features = ["env-filter"] } + +# tracing-forest = { path = "/Users/william/development/tracing-forest/tracing-forest" } +tracing-forest = { git = "https://github.com/QnnOkabayashi/tracing-forest.git", rev = "48d78f7294ceee47a22eee5c80964143c4fb3fe1" } + +url = "^2.3.1" +urlencoding = "2.1.2" +users = "^0.11.0" +uuid = "^1.1.2" + +validator = "^0.16.0" + +wasm-bindgen = "^0.2.81" +wasm-bindgen-futures = "^0.4.30" +wasm-bindgen-test = "0.3.33" webauthn-authenticator-rs = "0.4.7" webauthn-rs = "0.4.7" @@ -40,6 +151,13 @@ webauthn-rs-proto = "0.4.7" # webauthn-rs = { path = "../webauthn-rs/webauthn-rs" } # webauthn-rs-core = { path = "../webauthn-rs/webauthn-rs-core" } # webauthn-rs-proto = { path = "../webauthn-rs/webauthn-rs-proto" } +web-sys = "^0.3.60" +whoami = "^1.2.3" + +yew = "^0.19.3" +yew-agent = "^0.1.0" +yew-router = "^0.16.0" +zxcvbn = "^2.2.1" # enshrinken the WASMs [profile.release.package.kanidmd_web_ui] diff --git a/kanidm_client/Cargo.toml b/kanidm_client/Cargo.toml index be83b9fc4..cf8cdd1b0 100644 --- a/kanidm_client/Cargo.toml +++ b/kanidm_client/Cargo.toml @@ -1,25 +1,26 @@ [package] name = "kanidm_client" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.64" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Client Library" documentation = "https://docs.rs/kanidm_client/latest/kanidm_client/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [dependencies] -tracing = "^0.1.35" -reqwest = { version = "^0.11.11", features=["cookies", "json", "native-tls"] } -kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" } -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -time = { version = "=0.2.27", features = ["serde", "std"] } -tokio = { version = "^1.21.1", features = ["rt", "net", "time", "macros", "sync", "signal"] } -toml = "^0.5.9" -uuid = { version = "^1.1.2", features = ["serde", "v4"] } -url = { version = "^2.3.1", features = ["serde"] } +tracing.workspace = true +reqwest = { workspace = true, features=["cookies", "json", "native-tls"] } +kanidm_proto.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +time = { workspace = true, features = ["serde", "std"] } +tokio = { workspace = true, features = ["rt", "net", "time", "macros", "sync", "signal"] } +toml.workspace = true +uuid = { workspace = true, features = ["serde", "v4"] } +url = { workspace = true, features = ["serde"] } webauthn-rs-proto = { workspace = true, features = ["wasm"] } diff --git a/kanidm_client/src/lib.rs b/kanidm_client/src/lib.rs index ce788e192..17f693dee 100644 --- a/kanidm_client/src/lib.rs +++ b/kanidm_client/src/lib.rs @@ -13,32 +13,26 @@ #[macro_use] extern crate tracing; -use reqwest::header::CONTENT_TYPE; -use serde::de::DeserializeOwned; -use serde::Deserialize; -use serde::Serialize; -use serde_json::error::Error as SerdeJsonError; +use std::collections::{BTreeMap, BTreeSet as Set}; use std::fmt::{Display, Formatter}; use std::fs::File; #[cfg(target_family = "unix")] // not needed for windows builds use std::fs::{metadata, Metadata}; -use std::io::ErrorKind; -use std::io::Read; - +use std::io::{ErrorKind, Read}; #[cfg(target_family = "unix")] // not needed for windows builds use std::os::unix::fs::MetadataExt; - -use std::collections::BTreeMap; -use std::collections::BTreeSet as Set; use std::path::Path; use std::time::Duration; + +use kanidm_proto::v1::*; +use reqwest::header::CONTENT_TYPE; +pub use reqwest::StatusCode; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use serde_json::error::Error as SerdeJsonError; use tokio::sync::RwLock; use url::Url; use uuid::Uuid; - -pub use reqwest::StatusCode; - -use kanidm_proto::v1::*; use webauthn_rs_proto::{ PublicKeyCredential, RegisterPublicKeyCredential, RequestChallengeResponse, }; @@ -1767,6 +1761,7 @@ impl KanidmClient { self.perform_patch_request(format!("/v1/oauth2/{}", id).as_str(), update_oauth2_rs) .await } + pub async fn idm_oauth2_rs_prefer_spn_username(&self, id: &str) -> Result<(), ClientError> { let mut update_oauth2_rs = Entry { attrs: BTreeMap::new(), diff --git a/kanidm_client/src/person.rs b/kanidm_client/src/person.rs index 7da638571..f01678279 100644 --- a/kanidm_client/src/person.rs +++ b/kanidm_client/src/person.rs @@ -1,11 +1,9 @@ -use crate::ClientError; -use crate::KanidmClient; -use kanidm_proto::v1::AccountUnixExtend; -use kanidm_proto::v1::CredentialStatus; -use kanidm_proto::v1::Entry; -use kanidm_proto::v1::SingleStringRequest; use std::collections::BTreeMap; +use kanidm_proto::v1::{AccountUnixExtend, CredentialStatus, Entry, SingleStringRequest}; + +use crate::{ClientError, KanidmClient}; + impl KanidmClient { pub async fn idm_person_account_list(&self) -> Result, ClientError> { self.perform_get_request("/v1/person").await diff --git a/kanidm_client/src/service_account.rs b/kanidm_client/src/service_account.rs index 8b9cfe327..0a6930113 100644 --- a/kanidm_client/src/service_account.rs +++ b/kanidm_client/src/service_account.rs @@ -1,13 +1,11 @@ -use crate::ClientError; -use crate::KanidmClient; -use kanidm_proto::v1::AccountUnixExtend; -use kanidm_proto::v1::CredentialStatus; -use kanidm_proto::v1::Entry; -use kanidm_proto::v1::{ApiToken, ApiTokenGenerate}; use std::collections::BTreeMap; + +use kanidm_proto::v1::{AccountUnixExtend, ApiToken, ApiTokenGenerate, CredentialStatus, Entry}; use time::OffsetDateTime; use uuid::Uuid; +use crate::{ClientError, KanidmClient}; + impl KanidmClient { pub async fn idm_service_account_list(&self) -> Result, ClientError> { self.perform_get_request("/v1/service_account").await diff --git a/kanidm_proto/Cargo.toml b/kanidm_proto/Cargo.toml index d4b5b837e..000b4fd06 100644 --- a/kanidm_proto/Cargo.toml +++ b/kanidm_proto/Cargo.toml @@ -1,30 +1,30 @@ [package] name = "kanidm_proto" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.64" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Protocol Bindings for serde" documentation = "https://docs.rs/kanidm_proto/latest/kanidm_proto/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +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 = "^0.4.0" -base64urlsafedata = "0.1.0" -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -# Can not upgrade due to breaking timezone apis. -time = { version = "=0.2.27", features = ["serde", "std"] } -url = { version = "^2.3.1", features = ["serde"] } -urlencoding = "2.1.2" -uuid = { version = "^1.1.2", features = ["serde"] } +base32.workspace = true +base64urlsafedata.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +time = { workspace = true, features = ["serde", "std"] } +url = { workspace = true, features = ["serde"] } +urlencoding.workspace = true +uuid = { workspace = true, features = ["serde"] } webauthn-rs-proto.workspace = true [target.'cfg(not(target_family = "wasm"))'.dependencies] -last-git-commit = "0.2.0" +last-git-commit.workspace = true diff --git a/kanidm_proto/src/messages.rs b/kanidm_proto/src/messages.rs index 79e2f6a7d..1ce3e5640 100644 --- a/kanidm_proto/src/messages.rs +++ b/kanidm_proto/src/messages.rs @@ -1,9 +1,10 @@ // User-facing output things -use serde::{Deserialize, Serialize}; use std::fmt; use std::str::FromStr; +use serde::{Deserialize, Serialize}; + /// This is used in user-facing CLIs to set the formatting for output, /// and defaults to text. #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] @@ -21,6 +22,7 @@ impl Default for ConsoleOutputMode { impl FromStr for ConsoleOutputMode { type Err = &'static str; + /// This can be safely unwrap'd because it'll always return a default of text /// ``` /// use kanidm_proto::messages::ConsoleOutputMode; @@ -141,7 +143,6 @@ impl Default for AccountChangeMessage { /// msg.output_mode = ConsoleOutputMode::JSON; /// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\",\"src_user\":\"Kani\",\"dest_user\":\"Krabby\"}"; /// assert_eq!(format!("{}", msg), expected_result); -/// /// ``` impl fmt::Display for AccountChangeMessage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -149,7 +150,7 @@ impl fmt::Display for AccountChangeMessage { ConsoleOutputMode::JSON => write!( f, "{}", - serde_json::to_string(self).unwrap_or(format!("{:?}", self)) // if it fails to JSON serialize, just debug-dump it + serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */ ), ConsoleOutputMode::Text => write!( f, @@ -182,20 +183,20 @@ impl Default for BasicMessage { /// This outputs in either JSON or Text depending on the output_mode setting /// ``` -/// use std::fmt::format; /// use kanidm_proto::messages::*; +/// use std::fmt::format; /// let mut msg = BasicMessage::default(); -/// msg.action=String::from("cake_eating"); -/// msg.result=String::from("It was amazing"); +/// msg.action = String::from("cake_eating"); +/// msg.result = String::from("It was amazing"); /// assert_eq!(msg.status, MessageStatus::Success); /// /// let expected_result = "success - cake_eating: It was amazing"; /// assert_eq!(format!("{}", msg), expected_result); /// /// msg.output_mode = ConsoleOutputMode::JSON; -/// let expected_result = "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\"}"; +/// let expected_result = +/// "{\"action\":\"cake_eating\",\"result\":\"It was amazing\",\"status\":\"success\"}"; /// assert_eq!(format!("{}", msg), expected_result); -/// /// ``` impl fmt::Display for BasicMessage { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -203,7 +204,7 @@ impl fmt::Display for BasicMessage { ConsoleOutputMode::JSON => write!( f, "{}", - serde_json::to_string(self).unwrap_or(format!("{:?}", self)) // if it fails to JSON serialize, just debug-dump it + serde_json::to_string(self).unwrap_or(format!("{:?}", self)) /* if it fails to JSON serialize, just debug-dump it */ ), ConsoleOutputMode::Text => { write!(f, "{} - {}: {}", self.status, self.action, self.result,) diff --git a/kanidm_proto/src/oauth2.rs b/kanidm_proto/src/oauth2.rs index 987d0a345..a2c134356 100644 --- a/kanidm_proto/src/oauth2.rs +++ b/kanidm_proto/src/oauth2.rs @@ -1,6 +1,7 @@ +use std::collections::BTreeMap; + use base64urlsafedata::Base64UrlSafeData; use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; use url::Url; #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] diff --git a/kanidm_proto/src/v1.rs b/kanidm_proto/src/v1.rs index ef37de3e7..29ff9a2d4 100644 --- a/kanidm_proto/src/v1.rs +++ b/kanidm_proto/src/v1.rs @@ -1,8 +1,8 @@ -use serde::{Deserialize, Serialize}; use std::cmp::Ordering; -use std::collections::BTreeMap; -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; use std::fmt; + +use serde::{Deserialize, Serialize}; use uuid::Uuid; use webauthn_rs_proto::{ CreationChallengeResponse, PublicKeyCredential, RegisterPublicKeyCredential, @@ -1068,8 +1068,7 @@ impl SingleStringRequest { #[cfg(test)] mod tests { - use crate::v1::Filter as ProtoFilter; - use crate::v1::{TotpAlgo, TotpSecret}; + use crate::v1::{Filter as ProtoFilter, TotpAlgo, TotpSecret}; #[test] fn test_protofilter_simple() { diff --git a/kanidm_tools/Cargo.toml b/kanidm_tools/Cargo.toml index 293add408..01950e153 100644 --- a/kanidm_tools/Cargo.toml +++ b/kanidm_tools/Cargo.toml @@ -1,15 +1,16 @@ [package] name = "kanidm_tools" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.64" -edition = "2021" default-run = "kanidm" -license = "MPL-2.0" description = "Kanidm Client Tools" documentation = "https://docs.rs/kanidm_tools/latest/kanidm_tools/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [lib] name = "kanidm_cli" @@ -29,28 +30,28 @@ name = "kanidm_badlist_preprocess" path = "src/badlist_preprocess.rs" [dependencies] -clap = { version = "^3.2", features = ["derive", "env"] } -compact_jwt = "^0.2.3" -dialoguer = "^0.10.1" -libc = "^0.2.127" -kanidm_client = { path = "../kanidm_client", version = "1.1.0-alpha.8" } -kanidm_proto = { path = "../kanidm_proto", version = "1.1.0-alpha.8" } -qrcode = { version = "^0.12.0", default-features = false } -rayon = "^1.5.3" -rpassword = "^7.0.0" -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -shellexpand = "^2.1.2" -time = { version = "=0.2.27", features = ["serde", "std"] } -tracing = "^0.1.35" -tracing-subscriber = { version = "^0.3.14", features = ["env-filter", "fmt"] } -tokio = { version = "^1.21.1", features = ["rt", "macros"] } -url = { version = "^2.3.1", features = ["serde"] } -uuid = "^1.1.2" +clap = { workspace = true, features = ["derive", "env"] } +compact_jwt.workspace = true +dialoguer.workspace = true +libc.workspace = true +kanidm_client.workspace = true +kanidm_proto.workspace = true +qrcode = { workspace = true, default-features = false } +rayon.workspace = true +rpassword.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +shellexpand.workspace = true +time = { workspace = true, features = ["serde", "std"] } +tracing.workspace = true +tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] } +tokio = { workspace = true, features = ["rt", "macros"] } +url = { workspace = true, features = ["serde"] } +uuid.workspace = true webauthn-authenticator-rs = { workspace = true, features = ["u2fhid"] } -zxcvbn = "^2.2.1" +zxcvbn.workspace = true [build-dependencies] -clap = { version = "^3.2", features = ["derive"] } -clap_complete = { version = "^3.2.5"} -uuid = "^1.1.2" +clap = { workspace = true, features = ["derive"] } +clap_complete.workspace = true +uuid.workspace = true diff --git a/kanidm_tools/build.rs b/kanidm_tools/build.rs index 9468b3b44..0cd62aa96 100644 --- a/kanidm_tools/build.rs +++ b/kanidm_tools/build.rs @@ -2,10 +2,10 @@ use std::env; use std::path::PathBuf; -use uuid::Uuid; use clap::{CommandFactory, Parser}; use clap_complete::{generate_to, Shell}; +use uuid::Uuid; include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/badlist_preprocess.rs"); diff --git a/kanidm_tools/src/badlist_preprocess.rs b/kanidm_tools/src/badlist_preprocess.rs index 68e238853..5e9dceaf5 100644 --- a/kanidm_tools/src/badlist_preprocess.rs +++ b/kanidm_tools/src/badlist_preprocess.rs @@ -14,9 +14,8 @@ use std::io::BufWriter; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; -use kanidm_proto::v1::Modify; - use clap::Parser; +use kanidm_proto::v1::Modify; use rayon::prelude::*; use tracing::{debug, error, info}; diff --git a/kanidm_tools/src/cli/common.rs b/kanidm_tools/src/cli/common.rs index 71e89cdb2..d2cd0069e 100644 --- a/kanidm_tools/src/cli/common.rs +++ b/kanidm_tools/src/cli/common.rs @@ -1,11 +1,14 @@ -use crate::session::read_tokens; -use crate::CommonOpt; +use std::str::FromStr; + use compact_jwt::{Jws, JwsUnverified}; -use dialoguer::{theme::ColorfulTheme, Select}; +use dialoguer::theme::ColorfulTheme; +use dialoguer::Select; use kanidm_client::{KanidmClient, KanidmClientBuilder}; use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use kanidm_proto::v1::UserAuthToken; -use std::str::FromStr; + +use crate::session::read_tokens; +use crate::CommonOpt; impl CommonOpt { pub fn to_unauth_client(&self) -> KanidmClient { diff --git a/kanidm_tools/src/cli/lib.rs b/kanidm_tools/src/cli/lib.rs index ecf64dfa8..73f48821c 100644 --- a/kanidm_tools/src/cli/lib.rs +++ b/kanidm_tools/src/cli/lib.rs @@ -15,6 +15,7 @@ extern crate tracing; use std::path::PathBuf; + use uuid::Uuid; include!("../opt/kanidm.rs"); diff --git a/kanidm_tools/src/cli/main.rs b/kanidm_tools/src/cli/main.rs index 5c2c8fbc2..b9321208d 100644 --- a/kanidm_tools/src/cli/main.rs +++ b/kanidm_tools/src/cli/main.rs @@ -13,7 +13,8 @@ use clap::Parser; use kanidm_cli::KanidmClientParser; -use tracing_subscriber::{fmt, prelude::*, EnvFilter}; +use tracing_subscriber::prelude::*; +use tracing_subscriber::{fmt, EnvFilter}; #[tokio::main(flavor = "current_thread")] async fn main() { diff --git a/kanidm_tools/src/cli/person.rs b/kanidm_tools/src/cli/person.rs index 28da66ce9..809364510 100644 --- a/kanidm_tools/src/cli/person.rs +++ b/kanidm_tools/src/cli/person.rs @@ -1,22 +1,25 @@ -use crate::password_prompt; -use crate::{ - AccountCredential, AccountRadius, AccountSsh, AccountValidity, PersonOpt, PersonPosix, -}; -use dialoguer::{theme::ColorfulTheme, Select}; -use dialoguer::{Confirm, Input, Password}; +use std::fmt::{self, Debug}; +use std::str::FromStr; + +use dialoguer::theme::ColorfulTheme; +use dialoguer::{Confirm, Input, Password, Select}; use kanidm_client::ClientError::Http as ClientErrorHttp; use kanidm_client::KanidmClient; use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus}; use kanidm_proto::v1::OperationError::PasswordQuality; use kanidm_proto::v1::{CUIntentToken, CURegState, CUSessionToken, CUStatus, TotpSecret}; -use qrcode::{render::unicode, QrCode}; -use std::fmt::{self, Debug}; -use std::str::FromStr; +use qrcode::render::unicode; +use qrcode::QrCode; use time::OffsetDateTime; use url::Url; use uuid::Uuid; +use webauthn_authenticator_rs::u2fhid::U2FHid; +use webauthn_authenticator_rs::WebauthnAuthenticator; -use webauthn_authenticator_rs::{u2fhid::U2FHid, WebauthnAuthenticator}; +use crate::{ + password_prompt, AccountCredential, AccountRadius, AccountSsh, AccountValidity, PersonOpt, + PersonPosix, +}; impl PersonOpt { pub fn debug(&self) -> bool { diff --git a/kanidm_tools/src/cli/raw.rs b/kanidm_tools/src/cli/raw.rs index 99e33d186..fb7cb1907 100644 --- a/kanidm_tools/src/cli/raw.rs +++ b/kanidm_tools/src/cli/raw.rs @@ -1,14 +1,14 @@ -use crate::RawOpt; -use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList}; use std::collections::BTreeMap; - use std::error::Error; use std::fs::File; use std::io::BufReader; use std::path::Path; +use kanidm_proto::v1::{Entry, Filter, Modify, ModifyList}; use serde::de::DeserializeOwned; +use crate::RawOpt; + fn read_file>(path: P) -> Result> { let f = File::open(path)?; let r = BufReader::new(f); diff --git a/kanidm_tools/src/cli/serviceaccount.rs b/kanidm_tools/src/cli/serviceaccount.rs index 190945d31..af6a9b898 100644 --- a/kanidm_tools/src/cli/serviceaccount.rs +++ b/kanidm_tools/src/cli/serviceaccount.rs @@ -1,9 +1,10 @@ +use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus}; +use time::OffsetDateTime; + use crate::{ AccountSsh, AccountValidity, ServiceAccountApiToken, ServiceAccountCredential, ServiceAccountOpt, ServiceAccountPosix, }; -use kanidm_proto::messages::{AccountChangeMessage, ConsoleOutputMode, MessageStatus}; -use time::OffsetDateTime; impl ServiceAccountOpt { pub fn debug(&self) -> bool { diff --git a/kanidm_tools/src/cli/session.rs b/kanidm_tools/src/cli/session.rs index ab7c9870a..90bad6665 100644 --- a/kanidm_tools/src/cli/session.rs +++ b/kanidm_tools/src/cli/session.rs @@ -1,23 +1,22 @@ -use crate::common::prompt_for_username_get_username; -use crate::{LoginOpt, LogoutOpt, SessionOpt}; +use std::collections::BTreeMap; +use std::fs::{create_dir, File}; +use std::io::{self, BufReader, BufWriter, ErrorKind, Write}; +use std::path::PathBuf; +use std::str::FromStr; +use compact_jwt::JwsUnverified; +use dialoguer::theme::ColorfulTheme; +use dialoguer::Select; use kanidm_client::{ClientError, KanidmClient}; use kanidm_proto::v1::{AuthAllowed, AuthResponse, AuthState, UserAuthToken}; #[cfg(target_family = "unix")] use libc::umask; -use std::collections::BTreeMap; -use std::fs::{create_dir, File}; -use std::io::ErrorKind; -use std::io::{self, BufReader, BufWriter, Write}; -use std::path::PathBuf; -use std::str::FromStr; -use webauthn_authenticator_rs::{ - prelude::RequestChallengeResponse, u2fhid::U2FHid, WebauthnAuthenticator, -}; +use webauthn_authenticator_rs::prelude::RequestChallengeResponse; +use webauthn_authenticator_rs::u2fhid::U2FHid; +use webauthn_authenticator_rs::WebauthnAuthenticator; -use dialoguer::{theme::ColorfulTheme, Select}; - -use compact_jwt::JwsUnverified; +use crate::common::prompt_for_username_get_username; +use crate::{LoginOpt, LogoutOpt, SessionOpt}; static TOKEN_DIR: &str = "~/.cache"; static TOKEN_PATH: &str = "~/.cache/kanidm_tokens"; diff --git a/kanidm_tools/src/ssh_authorizedkeys.rs b/kanidm_tools/src/ssh_authorizedkeys.rs index 3de10f740..29b209d87 100644 --- a/kanidm_tools/src/ssh_authorizedkeys.rs +++ b/kanidm_tools/src/ssh_authorizedkeys.rs @@ -12,7 +12,6 @@ use std::path::PathBuf; use clap::Parser; use kanidm_client::{ClientError, KanidmClientBuilder}; - use kanidm_proto::constants::{DEFAULT_CLIENT_CONFIG_PATH, DEFAULT_CLIENT_CONFIG_PATH_HOME}; use tracing::{debug, error}; diff --git a/kanidm_unix_int/Cargo.toml b/kanidm_unix_int/Cargo.toml index 80f0d93a7..248182e4e 100644 --- a/kanidm_unix_int/Cargo.toml +++ b/kanidm_unix_int/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "kanidm_unix_int" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.64" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Unix Integration Clients" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [lib] name = "kanidm_unix_common" @@ -43,46 +44,42 @@ name = "kanidm_test_auth" path = "src/test_auth.rs" [dependencies] -kanidm_client = { path = "../kanidm_client" } -kanidm_proto = { path = "../kanidm_proto" } -kanidm = { path = "../kanidmd/idm" } +bytes.workspace = true +clap = { workspace = true, features = ["derive", "env"] } +futures.workspace = true +libc.workspace = true +libsqlite3-sys.workspace = true +lru.workspace = true +kanidm_client.workspace = true +kanidm_proto.workspace = true +# This is just used for password hashing and tests, so we could +# clean this up +kanidm.workspace = true -tracing = "^0.1.35" -sketching = { path = "../sketching" } +r2d2.workspace = true +r2d2_sqlite.workspace = true +rpassword.workspace = true +rusqlite.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +sketching.workspace = true -toml = "^0.5.9" -rpassword = "^7.0.0" -tokio = { version = "^1.21.1", features = ["rt", "macros", "sync", "time", "net", "io-util"] } -tokio-util = { version = "^0.7.4", features = ["codec"] } - -futures = "^0.3.21" -bytes = "^1.1.0" - -libc = "^0.2.127" -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -clap = { version = "^3.2", features = ["derive", "env"] } - -libsqlite3-sys = "0.25.0" -rusqlite = "^0.28.0" -r2d2 = "^0.8.10" -r2d2_sqlite = "^0.21.0" - -reqwest = "^0.11.11" - -users = "^0.11.0" - -lru = "^0.8.0" +toml.workspace = true +tokio = { workspace = true, features = ["rt", "macros", "sync", "time", "net", "io-util"] } +tokio-util = { workspace = true, features = ["codec"] } +tracing.workspace = true +reqwest.workspace = true +users.workspace = true [features] # default = [ "libsqlite3-sys/bundled" ] [dev-dependencies] # kanidm = { path = "../kanidmd/idm" } -score = { path = "../kanidmd/score" } +score.workspace = true [build-dependencies] -clap = { version = "^3.2", features = ["derive"] } -clap_complete = "^3.2.5" -profiles = { path = "../profiles" } +clap = { workspace = true, features = ["derive"] } +clap_complete.workspace = true +profiles.workspace = true diff --git a/kanidm_unix_int/build.rs b/kanidm_unix_int/build.rs index 83e5e6656..4e0898aba 100644 --- a/kanidm_unix_int/build.rs +++ b/kanidm_unix_int/build.rs @@ -1,11 +1,10 @@ #![allow(dead_code)] use std::env; +use std::path::PathBuf; use clap::{IntoApp, Parser}; use clap_complete::{generate_to, Shell}; -use std::path::PathBuf; - include!("src/opt/ssh_authorizedkeys.rs"); include!("src/opt/cache_invalidate.rs"); include!("src/opt/cache_clear.rs"); diff --git a/kanidm_unix_int/nss_kanidm/Cargo.toml b/kanidm_unix_int/nss_kanidm/Cargo.toml index 2759a262b..49d6292e0 100644 --- a/kanidm_unix_int/nss_kanidm/Cargo.toml +++ b/kanidm_unix_int/nss_kanidm/Cargo.toml @@ -1,9 +1,13 @@ [package] name = "nss_kanidm" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [lib] name = "nss_kanidm" @@ -11,9 +15,9 @@ crate-type = [ "cdylib" ] path = "src/lib.rs" [dependencies] -kanidm_unix_int = { path = "../" } -libnss = "^0.4.0" -libc = "^0.2.127" -paste = "^1.0.9" -lazy_static = "^1.4.0" +kanidm_unix_int.workspace = true +libnss.workspace = true +libc.workspace = true +paste.workspace = true +lazy_static.workspace = true diff --git a/kanidm_unix_int/nss_kanidm/src/lib.rs b/kanidm_unix_int/nss_kanidm/src/lib.rs index e41b9d731..84cea4273 100644 --- a/kanidm_unix_int/nss_kanidm/src/lib.rs +++ b/kanidm_unix_int/nss_kanidm/src/lib.rs @@ -19,7 +19,6 @@ use kanidm_unix_common::client_sync::call_daemon_blocking; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, NssGroup, NssUser}; - use libnss::group::{Group, GroupHooks}; use libnss::interop::Response; use libnss::passwd::{Passwd, PasswdHooks}; diff --git a/kanidm_unix_int/pam_kanidm/Cargo.toml b/kanidm_unix_int/pam_kanidm/Cargo.toml index 9db9c9bf5..d7931c623 100644 --- a/kanidm_unix_int/pam_kanidm/Cargo.toml +++ b/kanidm_unix_int/pam_kanidm/Cargo.toml @@ -1,19 +1,23 @@ [package] name = "pam_kanidm" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" links = "pam" +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" crate-type = [ "cdylib" ] path = "src/lib.rs" [dependencies] -kanidm_unix_int = { path = "../" } -libc = "^0.2.127" +kanidm_unix_int.workspace = true +libc.workspace = true [build-dependencies] -pkg-config = "^0.3.25" +pkg-config.workspace = true diff --git a/kanidm_unix_int/pam_kanidm/src/lib.rs b/kanidm_unix_int/pam_kanidm/src/lib.rs index e0b5996e6..f473e51ca 100644 --- a/kanidm_unix_int/pam_kanidm/src/lib.rs +++ b/kanidm_unix_int/pam_kanidm/src/lib.rs @@ -14,19 +14,20 @@ // extern crate libc; mod pam; -use crate::pam::constants::*; -use crate::pam::conv::PamConv; -use crate::pam::module::{PamHandle, PamHooks}; - use std::collections::BTreeSet; use std::convert::TryFrom; use std::ffi::CStr; + // use std::os::raw::c_char; use kanidm_unix_common::client_sync::call_daemon_blocking; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse}; +use crate::pam::constants::*; +use crate::pam::conv::PamConv; +use crate::pam::module::{PamHandle, PamHooks}; + #[derive(Debug)] struct Options { debug: bool, diff --git a/kanidm_unix_int/pam_kanidm/src/pam/conv.rs b/kanidm_unix_int/pam_kanidm/src/pam/conv.rs index aecc8d955..166fdf266 100644 --- a/kanidm_unix_int/pam_kanidm/src/pam/conv.rs +++ b/kanidm_unix_int/pam_kanidm/src/pam/conv.rs @@ -1,9 +1,9 @@ -use libc::{c_char, c_int}; use std::ffi::{CStr, CString}; use std::ptr; -use crate::pam::constants::PamResultCode; -use crate::pam::constants::*; +use libc::{c_char, c_int}; + +use crate::pam::constants::{PamResultCode, *}; use crate::pam::module::{PamItem, PamResult}; #[allow(missing_copy_implementations)] diff --git a/kanidm_unix_int/pam_kanidm/src/pam/macros.rs b/kanidm_unix_int/pam_kanidm/src/pam/macros.rs index 393beca9e..9986e28f1 100644 --- a/kanidm_unix_int/pam_kanidm/src/pam/macros.rs +++ b/kanidm_unix_int/pam_kanidm/src/pam/macros.rs @@ -7,10 +7,11 @@ /// Here is full example of a PAM module that would authenticate and authorize everybody: /// /// ``` -/// #[macro_use] extern crate pam; +/// #[macro_use] +/// extern crate pam; /// -/// use pam::module::{PamHooks, PamHandle}; -/// use pam::constants::{PamResultCode, PamFlag}; +/// use pam::constants::{PamFlag, PamResultCode}; +/// use pam::module::{PamHandle, PamHooks}; /// use std::ffi::CStr; /// /// # fn main() {} @@ -18,15 +19,15 @@ /// pam_hooks!(MyPamModule); /// /// impl PamHooks for MyPamModule { -/// fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { -/// println!("Everybody is authenticated!"); -/// PamResultCode::PAM_SUCCESS -/// } +/// fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { +/// println!("Everybody is authenticated!"); +/// PamResultCode::PAM_SUCCESS +/// } /// -/// fn acct_mgmt(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { -/// println!("Everybody is authorized!"); -/// PamResultCode::PAM_SUCCESS -/// } +/// fn acct_mgmt(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { +/// println!("Everybody is authorized!"); +/// PamResultCode::PAM_SUCCESS +/// } /// } /// ``` #[macro_export] @@ -36,6 +37,7 @@ macro_rules! pam_hooks { mod pam_hooks_scope { use std::ffi::CStr; use std::os::raw::{c_char, c_int}; + use $crate::pam::constants::{PamFlag, PamResultCode}; use $crate::pam::module::{PamHandle, PamHooks}; diff --git a/kanidm_unix_int/pam_kanidm/src/pam/module.rs b/kanidm_unix_int/pam_kanidm/src/pam/module.rs index 994768ff5..4760b75ea 100755 --- a/kanidm_unix_int/pam_kanidm/src/pam/module.rs +++ b/kanidm_unix_int/pam_kanidm/src/pam/module.rs @@ -1,9 +1,10 @@ //! Functions for use in pam modules. -use libc::c_char; use std::ffi::{CStr, CString}; use std::{mem, ptr}; +use libc::c_char; + use crate::pam::constants::{PamFlag, PamItemType, PamResultCode, PAM_AUTHTOK}; /// Opaque type, used as a pointer when making pam API calls. diff --git a/kanidm_unix_int/pam_tester/Cargo.toml b/kanidm_unix_int/pam_tester/Cargo.toml index b8634f588..bf0a279d8 100644 --- a/kanidm_unix_int/pam_tester/Cargo.toml +++ b/kanidm_unix_int/pam_tester/Cargo.toml @@ -1,11 +1,14 @@ [package] name = "pam_tester" -version = "0.1.2" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [dependencies] pam = "^0.7.0" + diff --git a/kanidm_unix_int/src/cache.rs b/kanidm_unix_int/src/cache.rs index 9b54b67b1..744568e5f 100644 --- a/kanidm_unix_int/src/cache.rs +++ b/kanidm_unix_int/src/cache.rs @@ -1,19 +1,20 @@ -use crate::db::Db; -use crate::unix_config::{HomeAttr, UidAttr}; -use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser}; -use kanidm_client::ClientError; -use kanidm_client::KanidmClient; -use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken}; -use lru::LruCache; -use reqwest::StatusCode; use std::collections::BTreeSet; use std::num::NonZeroUsize; use std::ops::{Add, Sub}; use std::path::Path; use std::string::ToString; use std::time::{Duration, SystemTime}; + +use kanidm_client::{ClientError, KanidmClient}; +use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken}; +use lru::LruCache; +use reqwest::StatusCode; use tokio::sync::{Mutex, RwLock}; +use crate::db::Db; +use crate::unix_config::{HomeAttr, UidAttr}; +use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser}; + const NXCACHE_SIZE: usize = 2048; #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/kanidm_unix_int/src/cache_clear.rs b/kanidm_unix_int/src/cache_clear.rs index 3101a7ea0..7dd3a5eae 100644 --- a/kanidm_unix_int/src/cache_clear.rs +++ b/kanidm_unix_int/src/cache_clear.rs @@ -14,9 +14,7 @@ extern crate tracing; use clap::Parser; - use futures::executor::block_on; - use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; diff --git a/kanidm_unix_int/src/cache_invalidate.rs b/kanidm_unix_int/src/cache_invalidate.rs index c6edf0200..0a59795aa 100644 --- a/kanidm_unix_int/src/cache_invalidate.rs +++ b/kanidm_unix_int/src/cache_invalidate.rs @@ -14,9 +14,7 @@ extern crate tracing; use clap::Parser; - use futures::executor::block_on; - use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; diff --git a/kanidm_unix_int/src/client.rs b/kanidm_unix_int/src/client.rs index fd10a8439..84ceec92a 100644 --- a/kanidm_unix_int/src/client.rs +++ b/kanidm_unix_int/src/client.rs @@ -1,9 +1,8 @@ -use bytes::{BufMut, BytesMut}; -use futures::SinkExt; -use futures::StreamExt; use std::error::Error; -use std::io::Error as IoError; -use std::io::ErrorKind; +use std::io::{Error as IoError, ErrorKind}; + +use bytes::{BufMut, BytesMut}; +use futures::{SinkExt, StreamExt}; use tokio::net::UnixStream; // use tokio::runtime::Builder; use tokio_util::codec::Framed; @@ -14,8 +13,8 @@ use crate::unix_proto::{ClientRequest, ClientResponse}; struct ClientCodec; impl Decoder for ClientCodec { - type Item = ClientResponse; type Error = IoError; + type Item = ClientResponse; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { match serde_json::from_slice::(&src) { diff --git a/kanidm_unix_int/src/client_sync.rs b/kanidm_unix_int/src/client_sync.rs index 16e19042f..42d2261e6 100644 --- a/kanidm_unix_int/src/client_sync.rs +++ b/kanidm_unix_int/src/client_sync.rs @@ -1,9 +1,6 @@ use std::error::Error; -use std::io::Error as IoError; -use std::io::ErrorKind; -use std::io::{Read, Write}; +use std::io::{Error as IoError, ErrorKind, Read, Write}; use std::os::unix::net::UnixStream; - use std::time::{Duration, SystemTime}; use crate::unix_proto::{ClientRequest, ClientResponse}; diff --git a/kanidm_unix_int/src/daemon.rs b/kanidm_unix_int/src/daemon.rs index 7701b882e..d03a62928 100644 --- a/kanidm_unix_int/src/daemon.rs +++ b/kanidm_unix_int/src/daemon.rs @@ -10,10 +10,18 @@ #![deny(clippy::needless_pass_by_value)] #![deny(clippy::trivially_copy_pass_by_ref)] +use std::error::Error; +use std::fs::metadata; +use std::io; +use std::io::{Error as IoError, ErrorKind}; +use std::os::unix::fs::MetadataExt; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use std::time::Duration; + use bytes::{BufMut, BytesMut}; use clap::{Arg, ArgAction, Command}; -use futures::SinkExt; -use futures::StreamExt; +use futures::{SinkExt, StreamExt}; use kanidm::utils::file_permissions_readonly; use kanidm_client::KanidmClientBuilder; use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH; @@ -22,22 +30,14 @@ use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse}; use libc::umask; -use sketching::tracing_forest::{self, traits::*, util::*}; -use std::error::Error; -use std::fs::metadata; -use std::io; -use std::io::Error as IoError; -use std::io::ErrorKind; -use std::os::unix::fs::MetadataExt; -use std::path::{Path, PathBuf}; -use std::sync::Arc; -use std::time::Duration; +use sketching::tracing_forest::traits::*; +use sketching::tracing_forest::util::*; +use sketching::tracing_forest::{self}; use tokio::net::{UnixListener, UnixStream}; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::oneshot; use tokio::time; -use tokio_util::codec::Framed; -use tokio_util::codec::{Decoder, Encoder}; +use tokio_util::codec::{Decoder, Encoder, Framed}; use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; //=== the codec @@ -47,8 +47,8 @@ type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>); struct ClientCodec; impl Decoder for ClientCodec { - type Item = ClientRequest; type Error = io::Error; + type Item = ClientRequest; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { match serde_json::from_slice::(&src) { @@ -85,8 +85,8 @@ impl ClientCodec { struct TaskCodec; impl Decoder for TaskCodec { - type Item = TaskResponse; type Error = io::Error; + type Item = TaskResponse; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { match serde_json::from_slice::(&src) { diff --git a/kanidm_unix_int/src/daemon_status.rs b/kanidm_unix_int/src/daemon_status.rs index afc9cf4bc..b8370b85e 100644 --- a/kanidm_unix_int/src/daemon_status.rs +++ b/kanidm_unix_int/src/daemon_status.rs @@ -13,12 +13,10 @@ #[macro_use] extern crate tracing; -use clap::Parser; - use std::path::PathBuf; +use clap::Parser; // use futures::executor::block_on; - use kanidm_unix_common::client_sync::call_daemon_blocking; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; diff --git a/kanidm_unix_int/src/db.rs b/kanidm_unix_int/src/db.rs index 99b763495..68473507a 100644 --- a/kanidm_unix_int/src/db.rs +++ b/kanidm_unix_int/src/db.rs @@ -1,17 +1,17 @@ -use kanidm_proto::v1::{UnixGroupToken, UnixUserToken}; -use libc::umask; -use r2d2::Pool; -use r2d2_sqlite::SqliteConnectionManager; use std::convert::TryFrom; use std::fmt; use std::time::Duration; -use crate::cache::Id; -use tokio::sync::{Mutex, MutexGuard}; - use kanidm::be::dbvalue::DbPasswordV1; use kanidm::credential::policy::CryptoPolicy; use kanidm::credential::Password; +use kanidm_proto::v1::{UnixGroupToken, UnixUserToken}; +use libc::umask; +use r2d2::Pool; +use r2d2_sqlite::SqliteConnectionManager; +use tokio::sync::{Mutex, MutexGuard}; + +use crate::cache::Id; pub struct Db { pool: Pool, @@ -732,9 +732,10 @@ impl<'a> Drop for DbTxn<'a> { #[cfg(test)] mod tests { + use kanidm_proto::v1::{UnixGroupToken, UnixUserToken}; + use super::Db; use crate::cache::Id; - use kanidm_proto::v1::{UnixGroupToken, UnixUserToken}; const TESTACCOUNT1_PASSWORD_A: &str = "password a for account1 test"; const TESTACCOUNT1_PASSWORD_B: &str = "password b for account1 test"; diff --git a/kanidm_unix_int/src/ssh_authorizedkeys.rs b/kanidm_unix_int/src/ssh_authorizedkeys.rs index 7aca8d673..4633b82f8 100644 --- a/kanidm_unix_int/src/ssh_authorizedkeys.rs +++ b/kanidm_unix_int/src/ssh_authorizedkeys.rs @@ -13,11 +13,10 @@ #[macro_use] extern crate tracing; -use clap::Parser; use std::path::PathBuf; +use clap::Parser; use futures::executor::block_on; - use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; diff --git a/kanidm_unix_int/src/tasks_daemon.rs b/kanidm_unix_int/src/tasks_daemon.rs index c9adeb3a6..ab89644ca 100644 --- a/kanidm_unix_int/src/tasks_daemon.rs +++ b/kanidm_unix_int/src/tasks_daemon.rs @@ -10,35 +10,31 @@ #![deny(clippy::needless_pass_by_value)] #![deny(clippy::trivially_copy_pass_by_ref)] -use users::{get_effective_gid, get_effective_uid}; - -use std::os::unix::fs::symlink; - -use libc::{lchown, umask}; use std::ffi::CString; - -use bytes::{BufMut, BytesMut}; -use futures::SinkExt; -use futures::StreamExt; -use sketching::tracing_forest::{self, traits::*, util::*}; -use std::fs; -use std::io; +use std::os::unix::fs::symlink; use std::path::Path; use std::time::Duration; -use tokio::net::UnixStream; -use tokio::time; -use tokio_util::codec::Framed; -use tokio_util::codec::{Decoder, Encoder}; +use std::{fs, io}; +use bytes::{BufMut, BytesMut}; +use futures::{SinkExt, StreamExt}; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_proto::{HomeDirectoryInfo, TaskRequest, TaskResponse}; +use libc::{lchown, umask}; +use sketching::tracing_forest::traits::*; +use sketching::tracing_forest::util::*; +use sketching::tracing_forest::{self}; +use tokio::net::UnixStream; +use tokio::time; +use tokio_util::codec::{Decoder, Encoder, Framed}; +use users::{get_effective_gid, get_effective_uid}; struct TaskCodec; impl Decoder for TaskCodec { - type Item = TaskRequest; type Error = io::Error; + type Item = TaskRequest; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { match serde_json::from_slice::(&src) { diff --git a/kanidm_unix_int/src/test_auth.rs b/kanidm_unix_int/src/test_auth.rs index 1cb3fa5d3..84dc55976 100644 --- a/kanidm_unix_int/src/test_auth.rs +++ b/kanidm_unix_int/src/test_auth.rs @@ -3,9 +3,7 @@ extern crate tracing; use clap::Parser; - use futures::executor::block_on; - use kanidm_unix_common::client::call_daemon; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::unix_config::KanidmUnixdConfig; diff --git a/kanidm_unix_int/src/unix_config.rs b/kanidm_unix_int/src/unix_config.rs index d7c9d0df6..aca10cd3d 100644 --- a/kanidm_unix_int/src/unix_config.rs +++ b/kanidm_unix_int/src/unix_config.rs @@ -1,15 +1,17 @@ -use crate::constants::{ - DEFAULT_CACHE_TIMEOUT, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_GID_ATTR_MAP, - DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_SOCK_PATH, - DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP, -}; -use serde::Deserialize; use std::env; use std::fmt::{Display, Formatter}; use std::fs::File; use std::io::{ErrorKind, Read}; use std::path::Path; +use serde::Deserialize; + +use crate::constants::{ + DEFAULT_CACHE_TIMEOUT, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_GID_ATTR_MAP, + DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_SOCK_PATH, + DEFAULT_TASK_SOCK_PATH, DEFAULT_UID_ATTR_MAP, +}; + #[derive(Debug, Deserialize)] struct ConfigInt { db_path: Option, diff --git a/kanidm_unix_int/tests/cache_layer_test.rs b/kanidm_unix_int/tests/cache_layer_test.rs index e42c11140..2ea53d103 100644 --- a/kanidm_unix_int/tests/cache_layer_test.rs +++ b/kanidm_unix_int/tests/cache_layer_test.rs @@ -1,23 +1,19 @@ #![deny(warnings)] +use std::future::Future; use std::net::TcpStream; +use std::pin::Pin; use std::sync::atomic::{AtomicU16, Ordering}; use std::time::Duration; use kanidm::audit::LogLevel; use kanidm::config::{Configuration, IntegrationTestConfig, ServerRole}; -use score::create_server_core; - +use kanidm_client::{KanidmClient, KanidmClientBuilder}; use kanidm_unix_common::cache::{CacheLayer, Id}; use kanidm_unix_common::constants::{ DEFAULT_GID_ATTR_MAP, DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_SHELL, DEFAULT_UID_ATTR_MAP, }; - -use kanidm_client::{KanidmClient, KanidmClientBuilder}; - -use std::future::Future; -use std::pin::Pin; - +use score::create_server_core; use tokio::task; static PORT_ALLOC: AtomicU16 = AtomicU16::new(28080); diff --git a/kanidmd/daemon/Cargo.toml b/kanidmd/daemon/Cargo.toml index 01bc04dbf..9ba1265a7 100644 --- a/kanidmd/daemon/Cargo.toml +++ b/kanidmd/daemon/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "daemon" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Server Daemon" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +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 @@ -17,25 +18,25 @@ name = "kanidmd" path = "src/main.rs" [dependencies] -kanidm = { path = "../idm" } -kanidm_proto = { path = "../../kanidm_proto" } -score = { path = "../score" } -sketching = { path = "../../sketching" } +kanidm.workspace = true +kanidm_proto.workspace = true +score.workspace = true +sketching.workspace = true -clap = { version = "^3.2", features = ["derive", "env"] } -serde = { version = "^1.0.142", features = ["derive"] } -tokio = { version = "^1.21.1", features = ["rt-multi-thread", "macros", "signal"] } -toml = "0.5.9" +clap = { workspace = true, features = ["env"] } +serde = { workspace = true, features = ["derive"] } +tokio = { workspace = true, features = ["rt-multi-thread", "macros", "signal"] } +toml.workspace = true [target.'cfg(target_family = "windows")'.dependencies] -whoami = "^1.2.3" +whoami.workspace = true [target.'cfg(not(target_family = "windows"))'.dependencies] -users = "^0.11.0" -tikv-jemallocator = "0.5" +users.workspace = true +tikv-jemallocator.workspace = true [build-dependencies] -serde = { version = "1", features = ["derive"] } -clap = { version = "^3.2", features = ["derive"] } -clap_complete = "^3.2.5" -profiles = { path = "../../profiles" } +serde = { workspace = true, features = ["derive"] } +clap = { workspace = true, features = ["derive"] } +clap_complete.workspace = true +profiles.workspace = true diff --git a/kanidmd/daemon/build.rs b/kanidmd/daemon/build.rs index e04885924..73ef51b0e 100644 --- a/kanidmd/daemon/build.rs +++ b/kanidmd/daemon/build.rs @@ -5,7 +5,6 @@ use std::path::PathBuf; use clap::{Args, IntoApp, Parser, Subcommand}; use clap_complete::{generate_to, Shell}; - use serde::{Deserialize, Serialize}; include!("../idm/src/audit_loglevel.rs"); diff --git a/kanidmd/daemon/src/main.rs b/kanidmd/daemon/src/main.rs index 4b08825d1..98cbd4878 100644 --- a/kanidmd/daemon/src/main.rs +++ b/kanidmd/daemon/src/main.rs @@ -14,25 +14,15 @@ #[global_allocator] static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; -#[cfg(not(target_family = "windows"))] // not needed for windows builds -use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; -#[cfg(target_family = "windows")] // for windows builds -use whoami; - -use serde::Deserialize; use std::fs::{metadata, File, Metadata}; - +use std::io::Read; #[cfg(target_family = "unix")] use std::os::unix::fs::MetadataExt; - -use std::io::Read; -use std::path::Path; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::exit; use std::str::FromStr; -use sketching::tracing_forest::{self, traits::*, util::*}; - +use clap::{Args, Parser, Subcommand}; use kanidm::audit::LogLevel; use kanidm::config::{Configuration, OnlineBackup, ServerRole}; #[cfg(not(target_family = "windows"))] @@ -43,8 +33,14 @@ use score::{ domain_rename_core, recover_account_core, reindex_server_core, restore_server_core, vacuum_server_core, verify_server_core, }; - -use clap::{Args, Parser, Subcommand}; +use serde::Deserialize; +use sketching::tracing_forest::traits::*; +use sketching::tracing_forest::util::*; +use sketching::tracing_forest::{self}; +#[cfg(not(target_family = "windows"))] // not needed for windows builds +use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; +#[cfg(target_family = "windows")] // for windows builds +use whoami; include!("./opt.rs"); diff --git a/kanidmd/idm/Cargo.toml b/kanidmd/idm/Cargo.toml index 8b994cc9c..ce55858d1 100644 --- a/kanidmd/idm/Cargo.toml +++ b/kanidmd/idm/Cargo.toml @@ -1,98 +1,91 @@ [package] name = "kanidm" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Server Library and Binary" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true [lib] name = "kanidm" path = "src/lib.rs" +[[bench]] +name = "scaling_10k" +harness = false + [dependencies] -async-std = { version = "^1.12.0", features = ["tokio1"] } -async-trait = "^0.1.57" -base64 = "^0.13.0" -base64urlsafedata = "0.1.0" -chrono = "^0.4.20" -compact_jwt = "^0.2.3" -concread = "^0.4.0" -dyn-clone = "^1.0.9" -fernet = { version = "^0.2.0", features = ["fernet_danger_timestamps"] } -filetime = "^0.2.17" -futures = "^0.3.21" -futures-util = "^0.3.21" -hashbrown = { version = "0.12.3", features = ["serde", "inline-more", "ahash"] } -idlset = { version = "^0.2.4" } -kanidm_proto = { path = "../../kanidm_proto" } -lazy_static = "^1.4.0" -ldap3_proto = "^0.2.3" -libc = "^0.2.127" -libsqlite3-sys = "^0.25.0" -num_enum = "^0.5.7" -openssl = "^0.10.41" -r2d2 = "^0.8.9" -r2d2_sqlite = "^0.21.0" -rand = "^0.8.5" -regex = "^1.5.6" -saffron = "^0.1.0" -serde = { version = "^1.0.142", features = ["derive"] } -serde_cbor = "^0.11.2" -serde_json = "^1.0.83" -smartstring = { version = "^1.0.1", features = ["serde"] } -smolset = "^1.3.1" -sshkeys = "^0.3.1" -tide = "^0.16.0" -time = { version = "=0.2.27", features = ["serde", "std"] } -tokio = { version = "^1.21.1", features = ["net", "sync", "time"] } -tokio-util = { version = "^0.7.4", features = ["codec"] } -toml = "^0.5.9" -touch = "^0.0.1" +async-std.workspace = true +async-trait.workspace = true +base64.workspace = true +base64urlsafedata.workspace = true +chrono.workspace = true +compact_jwt.workspace = true +concread.workspace = true +dyn-clone.workspace = true +fernet = { workspace = true, features = ["fernet_danger_timestamps"] } +filetime.workspace = true +futures.workspace = true +futures-util.workspace = true +hashbrown.workspace = true +idlset.workspace = true +kanidm_proto.workspace = true +lazy_static.workspace = true +ldap3_proto.workspace = true +libc.workspace = true +libsqlite3-sys.workspace = true +num_enum.workspace = true +openssl.workspace = true +r2d2.workspace = true +r2d2_sqlite.workspace = true +rand.workspace = true +regex.workspace = true +saffron.workspace = true +serde = { workspace = true, features = ["derive"] } +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 +time = { workspace = true, features = ["serde", "std"] } +tokio = { workspace = true, features = ["net", "sync", "time"] } +tokio-util = { workspace = true, features = ["codec"] } +toml.workspace = true +touch.workspace = true -sketching = { path = "../../sketching" } -tracing = { version = "^0.1.35", features = ["attributes"] } +tracing = { workspace = true, features = ["attributes"] } -url = { version = "^2.3.1", features = ["serde"] } -urlencoding = "2.1.2" -uuid = { version = "^1.1.2", features = ["serde", "v4" ] } -validator = { version = "^0.16.0", features = ["phone"] } +url = { workspace = true, features = ["serde"] } +urlencoding.workspace = true +uuid = { workspace = true, features = ["serde", "v4" ] } +validator = { workspace = true, features = ["phone"] } webauthn-rs = { workspace = true, features = ["resident-key-support", "preview-features", "danger-credential-internals"] } webauthn-rs-core.workspace = true -zxcvbn = "^2.2.1" +zxcvbn.workspace = true # because windows really can't build without the bundled one -[target.'cfg(target_family = "windows")'.dependencies.rusqlite] -version = "^0.28.0" -features = ["bundled"] - -[target.'cfg(not(target_family = "windows"))'.dependencies.rusqlite] -version = "^0.28.0" - [target.'cfg(target_family = "windows")'.dependencies] -whoami = "^1.2.3" - +rusqlite = { workspace = true, features = ["bundled"] } +whoami.workspace = true [target.'cfg(not(target_family = "windows"))'.dependencies] -users = "^0.11.0" - +rusqlite.workspace = true +users.workspace = true [features] # default = [ "libsqlite3-sys/bundled", "openssl/vendored" ] [dev-dependencies] -criterion = { version = "^0.4.0", features = ["html_reports"] } -# For testing webauthn +criterion = { workspace = true, features = ["html_reports"] } webauthn-authenticator-rs.workspace = true [build-dependencies] -profiles = { path = "../../profiles" } - -[[bench]] -name = "scaling_10k" -harness = false +profiles.workspace = true diff --git a/kanidmd/idm/benches/scaling_10k.rs b/kanidmd/idm/benches/scaling_10k.rs index f0aa25e3c..cc3a49ad6 100644 --- a/kanidmd/idm/benches/scaling_10k.rs +++ b/kanidmd/idm/benches/scaling_10k.rs @@ -1,7 +1,9 @@ +use std::time::{Duration, Instant}; + +use async_std::task; use criterion::{ criterion_group, criterion_main, BenchmarkId, Criterion, SamplingMode, Throughput, }; - use kanidm; use kanidm::entry::{Entry, EntryInit, EntryNew}; use kanidm::entry_init; @@ -11,9 +13,6 @@ use kanidm::server::QueryServer; use kanidm::utils::duration_from_epoch_now; use kanidm::value::Value; -use async_std::task; -use std::time::{Duration, Instant}; - pub fn scaling_user_create_single(c: &mut Criterion) { let mut group = c.benchmark_group("user_create_single"); group.sample_size(10); diff --git a/kanidmd/idm/src/access.rs b/kanidmd/idm/src/access.rs index 485c77c43..52deafe49 100644 --- a/kanidmd/idm/src/access.rs +++ b/kanidmd/idm/src/access.rs @@ -12,31 +12,28 @@ //! search. //! - the ability to turn an entry into a partial-entry for results send //! requirements (also search). -//! // use concread::collections::bptree::*; -use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn}; -use concread::cowcell::*; -use kanidm_proto::v1::Filter as ProtoFilter; -use kanidm_proto::v1::OperationError; -use std::collections::BTreeSet; // use hashbrown::HashSet; use std::cell::Cell; +use std::collections::BTreeSet; use std::ops::DerefMut; use std::sync::Arc; + +use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn}; +use concread::cowcell::*; +use kanidm_proto::v1::{Filter as ProtoFilter, OperationError}; +use tracing::trace; use uuid::Uuid; use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced, EntrySealed}; +use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent}; use crate::filter::{Filter, FilterValid, FilterValidResolved}; +use crate::identity::{IdentType, IdentityId}; use crate::modify::Modify; use crate::prelude::*; use crate::value::PartialValue; -use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent}; -use crate::identity::{IdentType, IdentityId}; - -use tracing::trace; - // const ACP_RELATED_SEARCH_CACHE_MAX: usize = 2048; // const ACP_RELATED_SEARCH_CACHE_LOCAL: usize = 16; @@ -408,6 +405,7 @@ pub trait AccessControlsTransaction<'a> { &self, ) -> &mut ARCacheReadTxn<'a, (IdentityId, Filter), Filter, ()>; + #[instrument(level = "debug", name = "access::search_related_acp", skip_all)] fn search_related_acp<'b>( &'b self, rec_entry: &Entry, @@ -443,61 +441,51 @@ pub trait AccessControlsTransaction<'a> { } else { */ // else, we calculate this, and then stash/cache the uuids. - let related_acp: Vec<(&AccessControlSearch, Filter)> = - spanned!("access::search_related_acp", { - search_state - .iter() - .filter_map(|acs| { - // Now resolve the receiver filter - // Okay, so in filter resolution, the primary error case - // is that we have a non-user in the event. We have already - // checked for this above BUT we should still check here - // properly just in case. - // - // In this case, we assume that if the event is internal - // that the receiver can NOT match because it has no selfuuid - // and can as a result, never return true. This leads to this - // acp not being considered in that case ... which should never - // happen because we already bypassed internal ops above! - // - // A possible solution is to change the filter resolve function - // such that it takes an entry, rather than an event, but that - // would create issues in search. - match (&acs.acp.receiver).resolve( - ident, - None, - Some(acp_resolve_filter_cache), - ) { - Ok(f_res) => { - if rec_entry.entry_match_no_index(&f_res) { - // Now, for each of the acp's that apply to our receiver, resolve their - // related target filters. - (&acs.acp.targetscope) - .resolve(ident, None, Some(acp_resolve_filter_cache)) - .map_err(|e| { - admin_error!( - ?e, - "A internal filter/event was passed for resolution!?!?" - ); - e - }) - .ok() - .map(|f_res| (acs, f_res)) - } else { - None - } - } - Err(e) => { - admin_error!( - ?e, - "A internal filter/event was passed for resolution!?!?" - ); - None - } + let related_acp: Vec<(&AccessControlSearch, Filter)> = search_state + .iter() + .filter_map(|acs| { + // Now resolve the receiver filter + // Okay, so in filter resolution, the primary error case + // is that we have a non-user in the event. We have already + // checked for this above BUT we should still check here + // properly just in case. + // + // In this case, we assume that if the event is internal + // that the receiver can NOT match because it has no selfuuid + // and can as a result, never return true. This leads to this + // acp not being considered in that case ... which should never + // happen because we already bypassed internal ops above! + // + // A possible solution is to change the filter resolve function + // such that it takes an entry, rather than an event, but that + // would create issues in search. + match (&acs.acp.receiver).resolve(ident, None, Some(acp_resolve_filter_cache)) { + Ok(f_res) => { + if rec_entry.entry_match_no_index(&f_res) { + // Now, for each of the acp's that apply to our receiver, resolve their + // related target filters. + (&acs.acp.targetscope) + .resolve(ident, None, Some(acp_resolve_filter_cache)) + .map_err(|e| { + admin_error!( + ?e, + "A internal filter/event was passed for resolution!?!?" + ); + e + }) + .ok() + .map(|f_res| (acs, f_res)) + } else { + None } - }) - .collect() - }); + } + Err(e) => { + admin_error!(?e, "A internal filter/event was passed for resolution!?!?"); + None + } + } + }) + .collect(); /* // Stash the uuids into the cache. @@ -511,6 +499,7 @@ pub trait AccessControlsTransaction<'a> { } // Contains all the way to eval acps to entries + #[instrument(level = "debug", name = "access::search_filter_entries", skip_all)] fn search_filter_entries( &self, se: &SearchEvent, @@ -525,27 +514,24 @@ pub trait AccessControlsTransaction<'a> { } IdentType::User(u) => &u.entry, }; - spanned!("access::search_filter_entries", { - trace!(event = %se.ident, "Access check for search (filter) event"); + trace!(event = %se.ident, "Access check for search (filter) event"); - // First get the set of acps that apply to this receiver - let related_acp: Vec<(&AccessControlSearch, _)> = - self.search_related_acp(rec_entry, &se.ident); + // First get the set of acps that apply to this receiver + let related_acp: Vec<(&AccessControlSearch, _)> = + self.search_related_acp(rec_entry, &se.ident); - /* - related_acp.iter().for_each(|racp| { - security_access!(acs = ?racp.acp.name, "Event Origin Related acs"); - }); - */ + /* + related_acp.iter().for_each(|racp| { + security_access!(acs = ?racp.acp.name, "Event Origin Related acs"); + }); + */ - // Get the set of attributes requested by this se filter. This is what we are - // going to access check. - let requested_attrs: BTreeSet<&str> = se.filter_orig.get_attr_set(); + // Get the set of attributes requested by this se filter. This is what we are + // going to access check. + let requested_attrs: BTreeSet<&str> = se.filter_orig.get_attr_set(); - // For each entry - let allowed_entries: Vec> = spanned!( - "access::search_filter_entries", - { + // For each entry + let allowed_entries: Vec> = entries .into_iter() .filter(|e| { @@ -580,20 +566,22 @@ pub trait AccessControlsTransaction<'a> { security_access!(?decision, "search attr decision"); decision }) - .collect() - } - ); + .collect(); - if allowed_entries.is_empty() { - security_access!("denied ❌"); - } else { - security_access!("allowed {} entries ✅", allowed_entries.len()); - } + if allowed_entries.is_empty() { + security_access!("denied ❌"); + } else { + security_access!("allowed {} entries ✅", allowed_entries.len()); + } - Ok(allowed_entries) - }) + Ok(allowed_entries) } + #[instrument( + level = "debug", + name = "access::search_filter_entry_attributes", + skip_all + )] fn search_filter_entry_attributes( &self, se: &SearchEvent, @@ -620,108 +608,100 @@ pub trait AccessControlsTransaction<'a> { IdentType::User(u) => &u.entry, }; - spanned!("access::search_filter_entry_attributes", { - /* - * Super similar to above (could even re-use some parts). Given a set of entries, - * reduce the attribute sets on them to "what is visible". This is ONLY called on - * the server edge, such that clients only see what they can, but internally, - * impersonate and such actually still get the whole entry back as not to break - * modify and co. - */ + /* + * Super similar to above (could even re-use some parts). Given a set of entries, + * reduce the attribute sets on them to "what is visible". This is ONLY called on + * the server edge, such that clients only see what they can, but internally, + * impersonate and such actually still get the whole entry back as not to break + * modify and co. + */ - trace!("Access check for search (reduce) event: {}", se.ident); + trace!("Access check for search (reduce) event: {}", se.ident); - // Get the relevant acps for this receiver. - let related_acp: Vec<(&AccessControlSearch, _)> = - self.search_related_acp(rec_entry, &se.ident); - let related_acp: Vec<(&AccessControlSearch, _)> = - if let Some(r_attrs) = se.attrs.as_ref() { - related_acp - .into_iter() - .filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs)) - .collect() - } else { - related_acp - }; + // Get the relevant acps for this receiver. + let related_acp: Vec<(&AccessControlSearch, _)> = + self.search_related_acp(rec_entry, &se.ident); + let related_acp: Vec<(&AccessControlSearch, _)> = if let Some(r_attrs) = se.attrs.as_ref() { + related_acp + .into_iter() + .filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs)) + .collect() + } else { + related_acp + }; - /* - related_acp.iter().for_each(|racp| { - lsecurity_access!( "Related acs -> {:?}", racp.acp.name); - }); - */ + /* + related_acp.iter().for_each(|racp| { + lsecurity_access!( "Related acs -> {:?}", racp.acp.name); + }); + */ - // Build a reference set from the req_attrs. This is what we test against - // to see if the attribute is something we currently want. - let req_attrs: Option> = se - .attrs - .as_ref() - .map(|vs| vs.iter().map(|s| s.as_str()).collect()); + // Build a reference set from the req_attrs. This is what we test against + // to see if the attribute is something we currently want. + let req_attrs: Option> = se + .attrs + .as_ref() + .map(|vs| vs.iter().map(|s| s.as_str()).collect()); - // For each entry - let allowed_entries: Vec> = - spanned!("access::search_filter_entry_attributes", { - entries - .into_iter() - .map(|e| { - // Get the set of attributes you can see for this entry - // this is within your related acp scope. - let allowed_attrs: BTreeSet<&str> = related_acp - .iter() - .filter_map(|(acs, f_res)| { - if e.entry_match_no_index(f_res) { - security_access!( - target = ?e.get_uuid(), - acs = %acs.acp.name, - "target entry matches acs", - ); - // add search_attrs to allowed iterator - Some(acs.attrs.iter().map(|s| s.as_str()).filter(|s| { - req_attrs - .as_ref() - .map(|r_attrs| r_attrs.contains(s)) - .unwrap_or(true) - })) - } else { - trace!( - target = ?e.get_uuid(), - acs = %acs.acp.name, - "target entry DOES NOT match acs", - ); - None - } - }) - .flatten() - .collect(); - - // Remove all others that are present on the entry. + // For each entry + let allowed_entries: Vec> = entries + .into_iter() + .map(|e| { + // Get the set of attributes you can see for this entry + // this is within your related acp scope. + let allowed_attrs: BTreeSet<&str> = related_acp + .iter() + .filter_map(|(acs, f_res)| { + if e.entry_match_no_index(f_res) { security_access!( - requested = ?req_attrs, - allowed = ?allowed_attrs, - "attributes" + target = ?e.get_uuid(), + acs = %acs.acp.name, + "target entry matches acs", ); + // add search_attrs to allowed iterator + Some(acs.attrs.iter().map(|s| s.as_str()).filter(|s| { + req_attrs + .as_ref() + .map(|r_attrs| r_attrs.contains(s)) + .unwrap_or(true) + })) + } else { + trace!( + target = ?e.get_uuid(), + acs = %acs.acp.name, + "target entry DOES NOT match acs", + ); + None + } + }) + .flatten() + .collect(); - // Now purge the attrs that are NOT allowed. - spanned!( - "access::search_filter_entry_attributes", - { e.reduce_attributes(&allowed_attrs) } - ) - }) - .collect() - }); - - if allowed_entries.is_empty() { - security_access!("reduced to empty set on all entries ❌"); - } else { + // Remove all others that are present on the entry. security_access!( - "attribute set reduced on {} entries ✅", - allowed_entries.len() + requested = ?req_attrs, + allowed = ?allowed_attrs, + "attributes" ); - } - Ok(allowed_entries) - }) + // Now purge the attrs that are NOT allowed. + e.reduce_attributes(&allowed_attrs) + }) + .collect(); + + if allowed_entries.is_empty() { + security_access!("reduced to empty set on all entries ❌"); + } else { + security_access!( + "attribute set reduced on {} entries ✅", + allowed_entries.len() + ); + } + + Ok(allowed_entries) } + #[instrument(level = "debug", name = "access::modify_related_acp", skip_all)] fn modify_related_acp<'b>( &'b self, rec_entry: &Entry, @@ -733,9 +713,7 @@ pub trait AccessControlsTransaction<'a> { // Find the acps that relate to the caller, and compile their related // target filters. - let related_acp: Vec<(&AccessControlModify, _)> = spanned!( - "access::modify_related_acp", - { + let related_acp: Vec<(&AccessControlModify, _)> = modify_state .iter() .filter_map(|acs| { @@ -766,14 +744,13 @@ pub trait AccessControlsTransaction<'a> { } } }) - .collect() - } - ); + .collect(); related_acp } #[allow(clippy::cognitive_complexity)] + #[instrument(level = "debug", name = "access::modify_allow_operation", skip_all)] fn modify_allow_operation( &self, me: &ModifyEvent, @@ -787,155 +764,154 @@ pub trait AccessControlsTransaction<'a> { } IdentType::User(u) => &u.entry, }; - spanned!("access::modify_allow_operation", { - trace!("Access check for modify event: {}", me.ident); + trace!("Access check for modify event: {}", me.ident); - // Pre-check if the no-no purge class is present - let disallow = me - .modlist - .iter() - .any(|m| matches!(m, Modify::Purged(a) if a == "class")); + // Pre-check if the no-no purge class is present + let disallow = me + .modlist + .iter() + .any(|m| matches!(m, Modify::Purged(a) if a == "class")); - if disallow { - security_access!("Disallowing purge class in modification"); - return Ok(false); - } + if disallow { + security_access!("Disallowing purge class in modification"); + return Ok(false); + } - // Find the acps that relate to the caller, and compile their related - // target filters. - let related_acp: Vec<(&AccessControlModify, _)> = - self.modify_related_acp(rec_entry, &me.ident); + // Find the acps that relate to the caller, and compile their related + // target filters. + let related_acp: Vec<(&AccessControlModify, _)> = + self.modify_related_acp(rec_entry, &me.ident); - related_acp.iter().for_each(|racp| { - trace!("Related acs -> {:?}", racp.0.acp.name); - }); + related_acp.iter().for_each(|racp| { + trace!("Related acs -> {:?}", racp.0.acp.name); + }); - // build two sets of "requested pres" and "requested rem" - let requested_pres: BTreeSet<&str> = me - .modlist - .iter() - .filter_map(|m| match m { - Modify::Present(a, _) => Some(a.as_str()), - _ => None, - }) - .collect(); + // build two sets of "requested pres" and "requested rem" + let requested_pres: BTreeSet<&str> = me + .modlist + .iter() + .filter_map(|m| match m { + Modify::Present(a, _) => Some(a.as_str()), + _ => None, + }) + .collect(); - let requested_rem: BTreeSet<&str> = me - .modlist - .iter() - .filter_map(|m| match m { - Modify::Removed(a, _) => Some(a.as_str()), - Modify::Purged(a) => Some(a.as_str()), - _ => None, - }) - .collect(); + let requested_rem: BTreeSet<&str> = me + .modlist + .iter() + .filter_map(|m| match m { + Modify::Removed(a, _) => Some(a.as_str()), + Modify::Purged(a) => Some(a.as_str()), + _ => None, + }) + .collect(); - // Build the set of classes that we to work on, only in terms of "addition". To remove - // I think we have no limit, but ... william of the future may find a problem with this - // policy. - let requested_classes: BTreeSet<&str> = me - .modlist - .iter() - .filter_map(|m| match m { - Modify::Present(a, v) => { - if a.as_str() == "class" { - // Here we have an option<&str> which could mean there is a risk of - // a malicious entity attempting to trick us by masking class mods - // in non-iutf8 types. However, the server first won't respect their - // existance, and second, we would have failed the mod at schema checking - // earlier in the process as these were not correctly type. As a result - // we can trust these to be correct here and not to be "None". - v.to_str() - } else { - None - } + // Build the set of classes that we to work on, only in terms of "addition". To remove + // I think we have no limit, but ... william of the future may find a problem with this + // policy. + let requested_classes: BTreeSet<&str> = me + .modlist + .iter() + .filter_map(|m| match m { + Modify::Present(a, v) => { + if a.as_str() == "class" { + // Here we have an option<&str> which could mean there is a risk of + // a malicious entity attempting to trick us by masking class mods + // in non-iutf8 types. However, the server first won't respect their + // existance, and second, we would have failed the mod at schema checking + // earlier in the process as these were not correctly type. As a result + // we can trust these to be correct here and not to be "None". + v.to_str() + } else { + None } - Modify::Removed(a, v) => { - if a.as_str() == "class" { - v.to_str() - } else { - None - } + } + Modify::Removed(a, v) => { + if a.as_str() == "class" { + v.to_str() + } else { + None + } + } + _ => None, + }) + .collect(); + + security_access!(?requested_pres, "Requested present set"); + security_access!(?requested_rem, "Requested remove set"); + security_access!(?requested_classes, "Requested class set"); + + let r = entries.iter().all(|e| { + // For this entry, find the acp's that apply to it from the + // set that apply to the entry that is performing the operation + let scoped_acp: Vec<&AccessControlModify> = related_acp + .iter() + .filter_map(|(acm, f_res)| { + if e.entry_match_no_index(f_res) { + Some(*acm) + } else { + None } - _ => None, }) .collect(); + // Build the sets of classes, pres and rem we are allowed to modify, extend + // or use based on the set of matched acps. + let allowed_pres: BTreeSet<&str> = scoped_acp + .iter() + .flat_map(|acp| acp.presattrs.iter().map(|v| v.as_str())) + .collect(); - security_access!(?requested_pres, "Requested present set"); - security_access!(?requested_rem, "Requested remove set"); - security_access!(?requested_classes, "Requested class set"); + let allowed_rem: BTreeSet<&str> = scoped_acp + .iter() + .flat_map(|acp| acp.remattrs.iter().map(|v| v.as_str())) + .collect(); - let r = entries.iter().all(|e| { - // For this entry, find the acp's that apply to it from the - // set that apply to the entry that is performing the operation - let scoped_acp: Vec<&AccessControlModify> = related_acp - .iter() - .filter_map(|(acm, f_res)| { - if e.entry_match_no_index(f_res) { - Some(*acm) - } else { - None - } - }) - .collect(); - // Build the sets of classes, pres and rem we are allowed to modify, extend - // or use based on the set of matched acps. - let allowed_pres: BTreeSet<&str> = scoped_acp - .iter() - .flat_map(|acp| acp.presattrs.iter().map(|v| v.as_str())) - .collect(); + let allowed_classes: BTreeSet<&str> = scoped_acp + .iter() + .flat_map(|acp| acp.classes.iter().map(|v| v.as_str())) + .collect(); - let allowed_rem: BTreeSet<&str> = scoped_acp - .iter() - .flat_map(|acp| acp.remattrs.iter().map(|v| v.as_str())) - .collect(); - - let allowed_classes: BTreeSet<&str> = scoped_acp - .iter() - .flat_map(|acp| acp.classes.iter().map(|v| v.as_str())) - .collect(); - - // Now check all the subsets are true. Remember, purge class - // is already checked above. - if !requested_pres.is_subset(&allowed_pres) { - security_access!("requested_pres is not a subset of allowed"); - security_access!( - "requested_pres: {:?} !⊆ allowed: {:?}", - requested_pres, - allowed_pres - ); - false - } else if !requested_rem.is_subset(&allowed_rem) { - security_access!("requested_rem is not a subset of allowed"); - security_access!( - "requested_rem: {:?} !⊆ allowed: {:?}", - requested_rem, - allowed_rem - ); - false - } else if !requested_classes.is_subset(&allowed_classes) { - security_access!("requested_classes is not a subset of allowed"); - security_access!( - "requested_classes: {:?} !⊆ allowed: {:?}", - requested_classes, - allowed_classes - ); - false - } else { - security_access!("passed pres, rem, classes check."); - true - } // if acc == false - }); - if r { - security_access!("allowed ✅"); + // Now check all the subsets are true. Remember, purge class + // is already checked above. + if !requested_pres.is_subset(&allowed_pres) { + security_access!("requested_pres is not a subset of allowed"); + security_access!( + "requested_pres: {:?} !⊆ allowed: {:?}", + requested_pres, + allowed_pres + ); + false + } else if !requested_rem.is_subset(&allowed_rem) { + security_access!("requested_rem is not a subset of allowed"); + security_access!( + "requested_rem: {:?} !⊆ allowed: {:?}", + requested_rem, + allowed_rem + ); + false + } else if !requested_classes.is_subset(&allowed_classes) { + security_access!("requested_classes is not a subset of allowed"); + security_access!( + "requested_classes: {:?} !⊆ allowed: {:?}", + requested_classes, + allowed_classes + ); + false } else { - security_access!("denied ❌"); - } - Ok(r) - }) + security_access!("passed pres, rem, classes check."); + true + } // if acc == false + }); + if r { + security_access!("allowed ✅"); + } else { + security_access!("denied ❌"); + } + Ok(r) } #[allow(clippy::cognitive_complexity)] + #[instrument(level = "debug", name = "access::create_allow_operation", skip_all)] fn create_allow_operation( &self, ce: &CreateEvent, @@ -949,125 +925,124 @@ pub trait AccessControlsTransaction<'a> { } IdentType::User(u) => &u.entry, }; - spanned!("access::create_allow_operation", { - trace!("Access check for create event: {}", ce.ident); + trace!("Access check for create event: {}", ce.ident); - // Some useful references we'll use for the remainder of the operation - let create_state = self.get_create(); - let acp_resolve_filter_cache = self.get_acp_resolve_filter_cache(); + // Some useful references we'll use for the remainder of the operation + let create_state = self.get_create(); + let acp_resolve_filter_cache = self.get_acp_resolve_filter_cache(); - // Find the acps that relate to the caller. - let related_acp: Vec<(&AccessControlCreate, _)> = create_state - .iter() - .filter_map(|acs| { - match acs + // Find the acps that relate to the caller. + let related_acp: Vec<(&AccessControlCreate, _)> = create_state + .iter() + .filter_map(|acs| { + match acs + .acp + .receiver + .resolve(&ce.ident, None, Some(acp_resolve_filter_cache)) + { + Ok(f_res) if rec_entry.entry_match_no_index(&f_res) => acs .acp - .receiver + .targetscope .resolve(&ce.ident, None, Some(acp_resolve_filter_cache)) - { - Ok(f_res) if rec_entry.entry_match_no_index(&f_res) => acs - .acp - .targetscope - .resolve(&ce.ident, None, Some(acp_resolve_filter_cache)) - .map_err(|e| { - admin_error!( - "A internal filter/event was passed for resolution!?!? {:?}", - e - ); - e - }) - .ok() - .map(|f_res| (acs, f_res)), - Ok(_) => None, - Err(e) => { + .map_err(|e| { admin_error!( "A internal filter/event was passed for resolution!?!? {:?}", e ); - None - } + e + }) + .ok() + .map(|f_res| (acs, f_res)), + Ok(_) => None, + Err(e) => { + admin_error!( + "A internal filter/event was passed for resolution!?!? {:?}", + e + ); + None } - }) - .collect(); + } + }) + .collect(); - // lsecurity_access!( "Related acc -> {:?}", related_acp); + // lsecurity_access!( "Related acc -> {:?}", related_acp); - // For each entry - let r = entries.iter().all(|e| { - // Build the set of requested classes and attrs here. - let create_attrs: BTreeSet<&str> = e.get_ava_names().collect(); - // If this is empty, we make an empty set, which is fine because - // the empty class set despite matching is_subset, will have the - // following effect: - // * there is no class on entry, so schema will fail - // * plugin-base will add object to give a class, but excess - // attrs will cause fail (could this be a weakness?) - // * class is a "may", so this could be empty in the rules, so - // if the accr is empty this would not be a true subset, - // so this would "fail", but any content in the accr would - // have to be validated. - // - // I still think if this is None, we should just fail here ... - // because it shouldn't be possible to match. + // For each entry + let r = entries.iter().all(|e| { + // Build the set of requested classes and attrs here. + let create_attrs: BTreeSet<&str> = e.get_ava_names().collect(); + // If this is empty, we make an empty set, which is fine because + // the empty class set despite matching is_subset, will have the + // following effect: + // * there is no class on entry, so schema will fail + // * plugin-base will add object to give a class, but excess + // attrs will cause fail (could this be a weakness?) + // * class is a "may", so this could be empty in the rules, so + // if the accr is empty this would not be a true subset, + // so this would "fail", but any content in the accr would + // have to be validated. + // + // I still think if this is None, we should just fail here ... + // because it shouldn't be possible to match. - let create_classes: BTreeSet<&str> = match e.get_ava_iter_iutf8("class") { - Some(s) => s.collect(), - None => { - admin_error!("Class set failed to build - corrupted entry?"); + let create_classes: BTreeSet<&str> = match e.get_ava_iter_iutf8("class") { + Some(s) => s.collect(), + None => { + admin_error!("Class set failed to build - corrupted entry?"); + return false; + } + }; + + related_acp.iter().any(|(accr, f_res)| { + // Check to see if allowed. + if e.entry_match_no_index(f_res) { + security_access!(?e, acs = ?accr, "entry matches acs"); + // It matches, so now we have to check attrs and classes. + // Remember, we have to match ALL requested attrs + // and classes to pass! + let allowed_attrs: BTreeSet<&str> = + accr.attrs.iter().map(|s| s.as_str()).collect(); + let allowed_classes: BTreeSet<&str> = + accr.classes.iter().map(|s| s.as_str()).collect(); + + if !create_attrs.is_subset(&allowed_attrs) { + security_access!("create_attrs is not a subset of allowed"); + security_access!("{:?} !⊆ {:?}", create_attrs, allowed_attrs); return false; } - }; - - related_acp.iter().any(|(accr, f_res)| { - // Check to see if allowed. - if e.entry_match_no_index(f_res) { - security_access!(?e, acs = ?accr, "entry matches acs"); - // It matches, so now we have to check attrs and classes. - // Remember, we have to match ALL requested attrs - // and classes to pass! - let allowed_attrs: BTreeSet<&str> = - accr.attrs.iter().map(|s| s.as_str()).collect(); - let allowed_classes: BTreeSet<&str> = - accr.classes.iter().map(|s| s.as_str()).collect(); - - if !create_attrs.is_subset(&allowed_attrs) { - security_access!("create_attrs is not a subset of allowed"); - security_access!("{:?} !⊆ {:?}", create_attrs, allowed_attrs); - return false; - } - if !create_classes.is_subset(&allowed_classes) { - security_access!("create_classes is not a subset of allowed"); - security_access!("{:?} !⊆ {:?}", create_classes, allowed_classes); - return false; - } - security_access!("passed"); - - true - } else { - trace!(?e, acs = %accr.acp.name, "entry DOES NOT match acs"); - // Does not match, fail this rule. - false + if !create_classes.is_subset(&allowed_classes) { + security_access!("create_classes is not a subset of allowed"); + security_access!("{:?} !⊆ {:?}", create_classes, allowed_classes); + return false; } - }) - // Find the set of related acps for this entry. - // - // For each "created" entry. - // If the created entry is 100% allowed by this acp - // IE: all attrs to be created AND classes match classes - // allow - // if no acp allows, fail operation. - }); + security_access!("passed"); - if r { - security_access!("allowed ✅"); - } else { - security_access!("denied ❌"); - } + true + } else { + trace!(?e, acs = %accr.acp.name, "entry DOES NOT match acs"); + // Does not match, fail this rule. + false + } + }) + // Find the set of related acps for this entry. + // + // For each "created" entry. + // If the created entry is 100% allowed by this acp + // IE: all attrs to be created AND classes match classes + // allow + // if no acp allows, fail operation. + }); - Ok(r) - }) + if r { + security_access!("allowed ✅"); + } else { + security_access!("denied ❌"); + } + + Ok(r) } + #[instrument(level = "debug", name = "access::delete_allow_operation", skip_all)] fn delete_allow_operation( &self, de: &DeleteEvent, @@ -1081,15 +1056,14 @@ pub trait AccessControlsTransaction<'a> { } IdentType::User(u) => &u.entry, }; - spanned!("access::delete_allow_operation", { - trace!("Access check for delete event: {}", de.ident); + trace!("Access check for delete event: {}", de.ident); - // Some useful references we'll use for the remainder of the operation - let delete_state = self.get_delete(); - let acp_resolve_filter_cache = self.get_acp_resolve_filter_cache(); + // Some useful references we'll use for the remainder of the operation + let delete_state = self.get_delete(); + let acp_resolve_filter_cache = self.get_acp_resolve_filter_cache(); - // Find the acps that relate to the caller. - let related_acp: Vec<(&AccessControlDelete, _)> = delete_state + // Find the acps that relate to the caller. + let related_acp: Vec<(&AccessControlDelete, _)> = delete_state .iter() .filter_map(|acs| { match acs.acp.receiver.resolve(&de.ident, None, Some(acp_resolve_filter_cache)) { @@ -1123,44 +1097,44 @@ pub trait AccessControlsTransaction<'a> { }) .collect(); - /* - related_acp.iter().for_each(|racp| { - lsecurity_access!( "Related acs -> {:?}", racp.acp.name); - }); - */ + /* + related_acp.iter().for_each(|racp| { + lsecurity_access!( "Related acs -> {:?}", racp.acp.name); + }); + */ - // For each entry - let r = entries.iter().all(|e| { - related_acp.iter().any(|(acd, f_res)| { - if e.entry_match_no_index(f_res) { - security_access!( - entry_uuid = ?e.get_uuid(), - acs = %acd.acp.name, - "entry matches acs" - ); - // It matches, so we can delete this! - security_access!("passed"); - true - } else { - trace!( - "entry {:?} DOES NOT match acs {}", - e.get_uuid(), - acd.acp.name - ); - // Does not match, fail. - false - } // else - }) // any related_acp - }); - if r { - security_access!("allowed ✅"); - } else { - security_access!("denied ❌"); - } - Ok(r) - }) + // For each entry + let r = entries.iter().all(|e| { + related_acp.iter().any(|(acd, f_res)| { + if e.entry_match_no_index(f_res) { + security_access!( + entry_uuid = ?e.get_uuid(), + acs = %acd.acp.name, + "entry matches acs" + ); + // It matches, so we can delete this! + security_access!("passed"); + true + } else { + trace!( + "entry {:?} DOES NOT match acs {}", + e.get_uuid(), + acd.acp.name + ); + // Does not match, fail. + false + } // else + }) // any related_acp + }); + if r { + security_access!("allowed ✅"); + } else { + security_access!("denied ❌"); + } + Ok(r) } + #[instrument(level = "debug", name = "access::effective_permission_check", skip_all)] fn effective_permission_check( &self, ident: &Identity, @@ -1186,116 +1160,114 @@ pub trait AccessControlsTransaction<'a> { IdentType::User(u) => &u.entry, }; - spanned!("access::effective_permission_check", { - trace!(ident = %ident, "Effective permission check"); - // I think we seperate this to multiple checks ...? + trace!(ident = %ident, "Effective permission check"); + // I think we seperate this to multiple checks ...? - // == search == - // Get the relevant acps for this receiver. - let search_related_acp: Vec<(&AccessControlSearch, _)> = - self.search_related_acp(rec_entry, ident); - let search_related_acp: Vec<(&AccessControlSearch, _)> = - if let Some(r_attrs) = attrs.as_ref() { - search_related_acp - .into_iter() - .filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs)) - .collect() + // == search == + // Get the relevant acps for this receiver. + let search_related_acp: Vec<(&AccessControlSearch, _)> = + self.search_related_acp(rec_entry, ident); + let search_related_acp: Vec<(&AccessControlSearch, _)> = + if let Some(r_attrs) = attrs.as_ref() { + search_related_acp + .into_iter() + .filter(|(acs, _)| !acs.attrs.is_disjoint(r_attrs)) + .collect() + } else { + search_related_acp + }; + + /* + search_related_acp.iter().for_each(|(racp, _)| { + trace!("Related acs -> {:?}", racp.acp.name); + }); + */ + + // == modify == + + let modify_related_acp: Vec<(&AccessControlModify, _)> = + self.modify_related_acp(rec_entry, ident); + + /* + modify_related_acp.iter().for_each(|(racp, _)| { + trace!("Related acm -> {:?}", racp.acp.name); + }); + */ + + let effective_permissions: Vec<_> = entries + .iter() + .map(|e| { + // == search == + let allowed_attrs: BTreeSet = search_related_acp + .iter() + .filter_map(|(acs, f_res)| { + // if it applies + if e.entry_match_no_index(f_res) { + // security_access!(entry = ?e.get_uuid(), acs = %acs.acp.name, "entry matches acs"); + Some(acs.attrs.iter().cloned()) + } else { + trace!(entry = ?e.get_uuid(), acs = %acs.acp.name, "entry DOES NOT match acs"); // should this be `security_access`? + None + } + }) + .flatten() + .collect(); + + security_access!( + requested = ?attrs, + allows = ?allowed_attrs, + "attributes", + ); + + // intersect? + let search_effective = if let Some(r_attrs) = attrs.as_ref() { + r_attrs & &allowed_attrs } else { - search_related_acp + allowed_attrs }; - /* - search_related_acp.iter().for_each(|(racp, _)| { - trace!("Related acs -> {:?}", racp.acp.name); - }); - */ + // == modify == + let modify_scoped_acp: Vec<&AccessControlModify> = modify_related_acp + .iter() + .filter_map(|(acm, f_res)| { + if e.entry_match_no_index(f_res) { + Some(*acm) + } else { + None + } + }) + .collect(); - // == modify == + let modify_pres: BTreeSet = modify_scoped_acp + .iter() + .flat_map(|acp| acp.presattrs.iter().cloned()) + .collect(); - let modify_related_acp: Vec<(&AccessControlModify, _)> = - self.modify_related_acp(rec_entry, ident); + let modify_rem: BTreeSet = modify_scoped_acp + .iter() + .flat_map(|acp| acp.remattrs.iter().cloned()) + .collect(); - /* - modify_related_acp.iter().for_each(|(racp, _)| { - trace!("Related acm -> {:?}", racp.acp.name); - }); - */ + let modify_class: BTreeSet = modify_scoped_acp + .iter() + .flat_map(|acp| acp.classes.iter().cloned()) + .collect(); - let effective_permissions: Vec<_> = entries - .iter() - .map(|e| { - // == search == - let allowed_attrs: BTreeSet = search_related_acp - .iter() - .filter_map(|(acs, f_res)| { - // if it applies - if e.entry_match_no_index(f_res) { - // security_access!(entry = ?e.get_uuid(), acs = %acs.acp.name, "entry matches acs"); - Some(acs.attrs.iter().cloned()) - } else { - trace!(entry = ?e.get_uuid(), acs = %acs.acp.name, "entry DOES NOT match acs"); // should this be `security_access`? - None - } - }) - .flatten() - .collect(); + AccessEffectivePermission { + target: e.get_uuid(), + search: search_effective, + modify_pres, + modify_rem, + modify_class, + } + }) + .collect(); - security_access!( - requested = ?attrs, - allows = ?allowed_attrs, - "attributes", - ); + effective_permissions.iter().for_each(|ep| { + trace!(?ep); + }); - // intersect? - let search_effective = if let Some(r_attrs) = attrs.as_ref() { - r_attrs & &allowed_attrs - } else { - allowed_attrs - }; - - // == modify == - let modify_scoped_acp: Vec<&AccessControlModify> = modify_related_acp - .iter() - .filter_map(|(acm, f_res)| { - if e.entry_match_no_index(f_res) { - Some(*acm) - } else { - None - } - }) - .collect(); - - let modify_pres: BTreeSet = modify_scoped_acp - .iter() - .flat_map(|acp| acp.presattrs.iter().cloned()) - .collect(); - - let modify_rem: BTreeSet = modify_scoped_acp - .iter() - .flat_map(|acp| acp.remattrs.iter().cloned()) - .collect(); - - let modify_class: BTreeSet = modify_scoped_acp - .iter() - .flat_map(|acp| acp.classes.iter().cloned()) - .collect(); - - AccessEffectivePermission { - target: e.get_uuid(), - search: search_effective, - modify_pres, - modify_rem, - modify_class, - } - }) - .collect(); - - effective_permissions.iter().for_each(|ep| { - trace!(?ep); - }); - - Ok(effective_permissions) - }) + Ok(effective_permissions) } } @@ -1522,15 +1494,17 @@ impl AccessControls { #[cfg(test)] mod tests { + use std::collections::BTreeSet; + use std::sync::Arc; + + use uuid::uuid; + use crate::access::{ AccessControlCreate, AccessControlDelete, AccessControlModify, AccessControlProfile, AccessControlSearch, AccessControls, AccessControlsTransaction, AccessEffectivePermission, }; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, SearchEvent}; use crate::prelude::*; - use std::collections::BTreeSet; - use std::sync::Arc; - use uuid::uuid; macro_rules! acp_from_entry_err { ( diff --git a/kanidmd/idm/src/actors/v1_read.rs b/kanidmd/idm/src/actors/v1_read.rs index 38d1cba8b..65db4166d 100644 --- a/kanidmd/idm/src/actors/v1_read.rs +++ b/kanidmd/idm/src/actors/v1_read.rs @@ -1,23 +1,28 @@ -use tracing::{error, info, instrument, trace}; - -use chrono::{DateTime, SecondsFormat, Utc}; +use std::convert::TryFrom; +use std::fs; +use std::path::{Path, PathBuf}; use std::sync::Arc; -use crate::prelude::*; +use kanidm_proto::v1::{ + ApiToken, AuthRequest, BackupCodesView, CURequest, CUSessionToken, CUStatus, CredentialStatus, + Entry as ProtoEntry, OperationError, RadiusAuthToken, SearchRequest, SearchResponse, + UnixGroupToken, UnixUserToken, WhoamiResponse, +}; +use ldap3_proto::simple::*; +use regex::Regex; +use tracing::{error, info, instrument, trace}; +use uuid::Uuid; use crate::be::BackendTransaction; - use crate::event::{ AuthEvent, AuthResult, OnlineBackupEvent, SearchEvent, SearchResult, WhoamiResult, }; +use crate::filter::{Filter, FilterInvalid}; use crate::idm::credupdatesession::CredentialUpdateSessionToken; use crate::idm::event::{ CredentialStatusEvent, RadiusAuthTokenEvent, ReadBackupCodeEvent, UnixGroupTokenEvent, UnixUserAuthEvent, UnixUserTokenEvent, }; -use kanidm_proto::v1::{BackupCodesView, OperationError, RadiusAuthToken}; - -use crate::filter::{Filter, FilterInvalid}; use crate::idm::oauth2::{ AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, AuthorisePermitSuccess, AuthoriseResponse, @@ -26,20 +31,7 @@ use crate::idm::oauth2::{ use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::serviceaccount::ListApiTokenEvent; use crate::ldap::{LdapBoundToken, LdapResponseState, LdapServer}; - -use kanidm_proto::v1::Entry as ProtoEntry; -use kanidm_proto::v1::{ - ApiToken, AuthRequest, CURequest, CUSessionToken, CUStatus, CredentialStatus, SearchRequest, - SearchResponse, UnixGroupToken, UnixUserToken, WhoamiResponse, -}; - -use regex::Regex; -use std::fs; -use std::path::{Path, PathBuf}; -use uuid::Uuid; - -use ldap3_proto::simple::*; -use std::convert::TryFrom; +use crate::prelude::*; // =========================================================== @@ -94,35 +86,25 @@ impl QueryServerReadV1 { // Begin a read let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - // ! NOTICE: The inner function contains a short-circuiting `return`, which is only exits the closure. - // ! If we removed the `lperf_op_segment` and kept the inside, this would short circuit before logging `audit`. - // ! However, since we immediately return `res` after logging `audit`, and we should be removing the lperf stuff - // ! and the logging of `audit` at the same time, it is ok if the inner code short circuits the whole function because - // ! there is no work to be done afterwards. - // ! However, if we want to do work after `res` is calculated, we need to pass `spanned` a closure instead of a block - // ! in order to not short-circuit the entire function. - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(?e, "Invalid identity"); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(?e, "Invalid identity"); + e + })?; - // Make an event from the request - let search = - SearchEvent::from_message(ident, &req, &idms_prox_read.qs_read).map_err(|e| { - admin_error!(?e, "Failed to begin search"); - e - })?; + // Make an event from the request + let search = + SearchEvent::from_message(ident, &req, &idms_prox_read.qs_read).map_err(|e| { + admin_error!(?e, "Failed to begin search"); + e + })?; - trace!(?search, "Begin event"); + trace!(?search, "Begin event"); - let entries = idms_prox_read.qs_read.search_ext(&search)?; + let entries = idms_prox_read.qs_read.search_ext(&search)?; - SearchResult::new(&idms_prox_read.qs_read, &entries).map(SearchResult::response) - }); - res + SearchResult::new(&idms_prox_read.qs_read, &entries).map(SearchResult::response) } #[instrument( @@ -184,34 +166,33 @@ impl QueryServerReadV1 { ) -> Result<(), OperationError> { trace!(eventid = ?msg.eventid, "Begin online backup event"); - let now: DateTime = Utc::now(); - let timestamp = now.to_rfc3339_opts(SecondsFormat::Secs, true); + #[allow(deprecated)] + let now = time::OffsetDateTime::now_local(); + let timestamp = now.format(time::Format::Rfc3339); let dest_file = format!("{}/backup-{}.json", outpath, timestamp); - match Path::new(&dest_file).exists() { - true => { - error!( - "Online backup file {} already exists, will not owerwrite it.", - dest_file - ); - return Err(OperationError::InvalidState); - } - false => { - let idms_prox_read = self.idms.proxy_read_async().await; - spanned!("actors::v1_read::handle", { - idms_prox_read - .qs_read - .get_be_txn() - .backup(&dest_file) - .map(|()| { - info!("Online backup created {} successfully", dest_file); - }) - .map_err(|e| { - error!("Online backup failed to create {}: {:?}", dest_file, e); - OperationError::InvalidState - })?; - }); - } + if Path::new(&dest_file).exists() { + error!( + "Online backup file {} already exists, will not overwrite it.", + dest_file + ); + return Err(OperationError::InvalidState); + } + + // Scope to limit the read txn. + { + let idms_prox_read = self.idms.proxy_read_async().await; + idms_prox_read + .qs_read + .get_be_txn() + .backup(&dest_file) + .map(|()| { + info!("Online backup created {} successfully", dest_file); + }) + .map_err(|e| { + error!("Online backup failed to create {}: {:?}", dest_file, e); + OperationError::InvalidState + })?; } // pattern to find automatically generated backup files @@ -314,53 +295,42 @@ impl QueryServerReadV1 { // Begin a read let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - // ! NOTICE: The inner function contains a short-circuiting `return`, which is only exits the closure. - // ! If we removed the `lperf_op_segment` and kept the inside, this would short circuit before logging `audit`. - // ! However, since we immediately return `res` after logging `audit`, and we should be removing the lperf stuff - // ! and the logging of `audit` at the same time, it is ok if the inner code short circuits the whole function because - // ! there is no work to be done afterwards. - // ! However, if we want to do work after `res` is calculated, we need to pass `spanned` a closure instead of a block - // ! in order to not short-circuit the entire function. - let res = spanned!("actors::v1_read::handle", { - // Make an event from the whoami request. This will process the event and - // generate a selfuuid search. - // - // This current handles the unauthenticated check, and will - // trigger the failure, but if we can manage to work out async - // then move this to core.rs, and don't allow Option to get - // this far. - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(?e, "Invalid identity"); - e - })?; + // Make an event from the whoami request. This will process the event and + // generate a selfuuid search. + // + // This current handles the unauthenticated check, and will + // trigger the failure, but if we can manage to work out async + // then move this to core.rs, and don't allow Option to get + // this far. + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(?e, "Invalid identity"); + e + })?; - let srch = - SearchEvent::from_whoami_request(ident, &idms_prox_read.qs_read).map_err(|e| { - admin_error!(?e, "Failed to begin whoami"); - e - })?; + let srch = + SearchEvent::from_whoami_request(ident, &idms_prox_read.qs_read).map_err(|e| { + admin_error!(?e, "Failed to begin whoami"); + e + })?; - trace!(search = ?srch, "Begin event"); + trace!(search = ?srch, "Begin event"); - let mut entries = idms_prox_read.qs_read.search_ext(&srch)?; + let mut entries = idms_prox_read.qs_read.search_ext(&srch)?; - match entries.pop() { - Some(e) if entries.is_empty() => { - WhoamiResult::new(&idms_prox_read.qs_read, &e).map(WhoamiResult::response) - } - Some(_) => Err(OperationError::InvalidState), // Somehow matched multiple entries... - _ => Err(OperationError::NoMatchingEntries), + match entries.pop() { + Some(e) if entries.is_empty() => { + WhoamiResult::new(&idms_prox_read.qs_read, &e).map(WhoamiResult::response) } - }); - res + Some(_) => Err(OperationError::InvalidState), /* Somehow matched multiple entries... */ + _ => Err(OperationError::NoMatchingEntries), + } } #[instrument( level = "info", - name = "search2", - skip(self, uat, filter, attrs, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalsearch( @@ -372,42 +342,38 @@ impl QueryServerReadV1 { ) -> Result, OperationError> { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - // Make an event from the request - let srch = match SearchEvent::from_internal_message( - ident, - &filter, - attrs.as_deref(), - &idms_prox_read.qs_read, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin internal api search: {:?}", e); - return Err(e); - } - }; - - trace!(?srch, "Begin event"); - - match idms_prox_read.qs_read.search_ext(&srch) { - Ok(entries) => SearchResult::new(&idms_prox_read.qs_read, &entries) - .map(|ok_sr| ok_sr.into_proto_array()), - Err(e) => Err(e), + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; + // Make an event from the request + let srch = match SearchEvent::from_internal_message( + ident, + &filter, + attrs.as_deref(), + &idms_prox_read.qs_read, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin internal api search: {:?}", e); + return Err(e); } - }); - res + }; + + trace!(?srch, "Begin event"); + + match idms_prox_read.qs_read.search_ext(&srch) { + Ok(entries) => SearchResult::new(&idms_prox_read.qs_read, &entries) + .map(|ok_sr| ok_sr.into_proto_array()), + Err(e) => Err(e), + } } #[instrument( level = "info", - name = "search_recycled", - skip(self, uat, filter, attrs, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalsearchrecycled( @@ -420,42 +386,38 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - // Make an event from the request - let srch = match SearchEvent::from_internal_recycle_message( - ident, - &filter, - attrs.as_deref(), - &idms_prox_read.qs_read, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin recycled search: {:?}", e); - return Err(e); - } - }; - - trace!(?srch, "Begin event"); - - match idms_prox_read.qs_read.search_ext(&srch) { - Ok(entries) => SearchResult::new(&idms_prox_read.qs_read, &entries) - .map(|ok_sr| ok_sr.into_proto_array()), - Err(e) => Err(e), + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; + // Make an event from the request + let srch = match SearchEvent::from_internal_recycle_message( + ident, + &filter, + attrs.as_deref(), + &idms_prox_read.qs_read, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin recycled search: {:?}", e); + return Err(e); } - }); - res + }; + + trace!(?srch, "Begin event"); + + match idms_prox_read.qs_read.search_ext(&srch) { + Ok(entries) => SearchResult::new(&idms_prox_read.qs_read, &entries) + .map(|ok_sr| ok_sr.into_proto_array()), + Err(e) => Err(e), + } } #[instrument( level = "info", - name = "radius_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalradiusread( @@ -466,60 +428,56 @@ impl QueryServerReadV1 { ) -> Result, OperationError> { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!("Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!("Error resolving id to target"); + e + })?; - // Make an event from the request - let srch = match SearchEvent::from_target_uuid_request( - ident, - target_uuid, - &idms_prox_read.qs_read, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin radius read: {:?}", e); - return Err(e); - } - }; - - trace!(?srch, "Begin event"); - - // We have to use search_ext to guarantee acs was applied. - match idms_prox_read.qs_read.search_ext(&srch) { - Ok(mut entries) => { - let r = entries - .pop() - // From the entry, turn it into the value - .and_then(|entry| { - entry - .get_ava_single("radius_secret") - .and_then(|v| v.get_secret_str().map(str::to_string)) - }); - Ok(r) - } - Err(e) => Err(e), + // Make an event from the request + let srch = match SearchEvent::from_target_uuid_request( + ident, + target_uuid, + &idms_prox_read.qs_read, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin radius read: {:?}", e); + return Err(e); } - }); - res + }; + + trace!(?srch, "Begin event"); + + // We have to use search_ext to guarantee acs was applied. + match idms_prox_read.qs_read.search_ext(&srch) { + Ok(mut entries) => { + let r = entries + .pop() + // From the entry, turn it into the value + .and_then(|entry| { + entry + .get_ava_single("radius_secret") + .and_then(|v| v.get_secret_str().map(str::to_string)) + }); + Ok(r) + } + Err(e) => Err(e), + } } #[instrument( level = "info", - name = "radius_token_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalradiustokenread( @@ -531,46 +489,42 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let mut idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!("Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!("Error resolving id to target"); + e + })?; - // Make an event from the request - let rate = match RadiusAuthTokenEvent::from_parts( - // &idms_prox_read.qs_read, - ident, - target_uuid, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin radius token read: {:?}", e); - return Err(e); - } - }; + // Make an event from the request + let rate = match RadiusAuthTokenEvent::from_parts( + // &idms_prox_read.qs_read, + ident, + target_uuid, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin radius token read: {:?}", e); + return Err(e); + } + }; - trace!(?rate, "Begin event"); + trace!(?rate, "Begin event"); - idms_prox_read.get_radiusauthtoken(&rate, ct) - }); - res + idms_prox_read.get_radiusauthtoken(&rate, ct) } #[instrument( level = "info", - name = "unix_user_token_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalunixusertokenread( @@ -582,49 +536,42 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let mut idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!( - "actors::v1_read::handle", - { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_info!( - err = ?e, - "Error resolving {} as gidnumber continuing ...", - uuid_or_name - ); - e - })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_info!( + err = ?e, + "Error resolving {} as gidnumber continuing ...", + uuid_or_name + ); + e + })?; - // Make an event from the request - let rate = match UnixUserTokenEvent::from_parts(ident, target_uuid) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin unix token read: {:?}", e); - return Err(e); - } - }; - - trace!(?rate, "Begin event"); - - idms_prox_read.get_unixusertoken(&rate, ct) + // Make an event from the request + let rate = match UnixUserTokenEvent::from_parts(ident, target_uuid) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin unix token read: {:?}", e); + return Err(e); } - ); - res + }; + + trace!(?rate, "Begin event"); + + idms_prox_read.get_unixusertoken(&rate, ct) } #[instrument( level = "info", - name = "unix_group_token_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalunixgrouptokenread( @@ -635,49 +582,42 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let mut idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!( - "actors::v1_read::handle", - { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_info!(err = ?e, "Error resolving as gidnumber continuing"); - e - })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_info!(err = ?e, "Error resolving as gidnumber continuing"); + e + })?; - // Make an event from the request - let rate = match UnixGroupTokenEvent::from_parts( - // &idms_prox_read.qs_read, - ident, - target_uuid, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin unix group token read: {:?}", e); - return Err(e); - } - }; - - trace!(?rate, "Begin event"); - - idms_prox_read.get_unixgrouptoken(&rate) + // Make an event from the request + let rate = match UnixGroupTokenEvent::from_parts( + // &idms_prox_read.qs_read, + ident, + target_uuid, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin unix group token read: {:?}", e); + return Err(e); } - ); - res + }; + + trace!(?rate, "Begin event"); + + idms_prox_read.get_unixgrouptoken(&rate) } #[instrument( level = "info", - name = "ssh_key_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalsshkeyread( @@ -688,62 +628,58 @@ impl QueryServerReadV1 { ) -> Result, OperationError> { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!("Error resolving id to target"); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!("Error resolving id to target"); + e + })?; - // Make an event from the request - let srch = match SearchEvent::from_target_uuid_request( - ident, - target_uuid, - &idms_prox_read.qs_read, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin ssh key read: {:?}", e); - return Err(e); - } - }; - - trace!(?srch, "Begin event"); - - match idms_prox_read.qs_read.search_ext(&srch) { - Ok(mut entries) => { - let r = entries - .pop() - // get the first entry - .and_then(|e| { - // From the entry, turn it into the value - e.get_ava_iter_sshpubkeys("ssh_publickey") - .map(|i| i.map(|s| s.to_string()).collect()) - }) - .unwrap_or_else(|| { - // No matching entry? Return none. - Vec::new() - }); - Ok(r) - } - Err(e) => Err(e), + // Make an event from the request + let srch = match SearchEvent::from_target_uuid_request( + ident, + target_uuid, + &idms_prox_read.qs_read, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin ssh key read: {:?}", e); + return Err(e); } - }); - res + }; + + trace!(?srch, "Begin event"); + + match idms_prox_read.qs_read.search_ext(&srch) { + Ok(mut entries) => { + let r = entries + .pop() + // get the first entry + .and_then(|e| { + // From the entry, turn it into the value + e.get_ava_iter_sshpubkeys("ssh_publickey") + .map(|i| i.map(|s| s.to_string()).collect()) + }) + .unwrap_or_else(|| { + // No matching entry? Return none. + Vec::new() + }); + Ok(r) + } + Err(e) => Err(e), + } } #[instrument( level = "info", - name = "ssh_key_tag_read", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalsshkeytagread( @@ -755,64 +691,60 @@ impl QueryServerReadV1 { ) -> Result, OperationError> { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_info!("Error resolving id to target"); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_info!("Error resolving id to target"); + e + })?; - // Make an event from the request - let srch = match SearchEvent::from_target_uuid_request( - ident, - target_uuid, - &idms_prox_read.qs_read, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin sshkey tag read: {:?}", e); - return Err(e); - } - }; - - trace!(?srch, "Begin event"); - - match idms_prox_read.qs_read.search_ext(&srch) { - Ok(mut entries) => { - let r = entries - .pop() - // get the first entry - .map(|e| { - // From the entry, turn it into the value - e.get_ava_set("ssh_publickey").and_then(|vs| { - // Get the one tagged value - vs.get_ssh_tag(&tag).map(str::to_string) - }) - }) - .unwrap_or_else(|| { - // No matching entry? Return none. - None - }); - Ok(r) - } - Err(e) => Err(e), + // Make an event from the request + let srch = match SearchEvent::from_target_uuid_request( + ident, + target_uuid, + &idms_prox_read.qs_read, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin sshkey tag read: {:?}", e); + return Err(e); } - }); - res + }; + + trace!(?srch, "Begin event"); + + match idms_prox_read.qs_read.search_ext(&srch) { + Ok(mut entries) => { + let r = entries + .pop() + // get the first entry + .map(|e| { + // From the entry, turn it into the value + e.get_ava_set("ssh_publickey").and_then(|vs| { + // Get the one tagged value + vs.get_ssh_tag(&tag).map(str::to_string) + }) + }) + .unwrap_or_else(|| { + // No matching entry? Return none. + None + }); + Ok(r) + } + Err(e) => Err(e), + } } #[instrument( level = "info", - name = "service_account_api_token_get", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_service_account_api_token_get( @@ -844,8 +776,7 @@ impl QueryServerReadV1 { #[instrument( level = "info", - name = "idm_account_unix_auth", - skip(self, uat, uuid_or_name, cred, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmaccountunixauth( @@ -857,7 +788,6 @@ impl QueryServerReadV1 { ) -> Result, OperationError> { let ct = duration_from_epoch_now(); let mut idm_auth = self.idms.auth_async().await; - // let res = spanned!("actors::v1_read::handle", { // resolve the id let ident = idm_auth .validate_and_parse_token_to_ident(uat.as_deref(), ct) @@ -891,14 +821,12 @@ impl QueryServerReadV1 { security_info!(?res, "Sending result"); - // res }); res } #[instrument( level = "info", - name = "idm_credential_status", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialstatus( @@ -910,45 +838,41 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let mut idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - // Make an event from the request - let cse = match CredentialStatusEvent::from_parts( - // &idms_prox_read.qs_read, - ident, - target_uuid, - ) { - Ok(s) => s, - Err(e) => { - admin_error!(err = ?e, "Failed to begin credential status read"); - return Err(e); - } - }; + // Make an event from the request + let cse = match CredentialStatusEvent::from_parts( + // &idms_prox_read.qs_read, + ident, + target_uuid, + ) { + Ok(s) => s, + Err(e) => { + admin_error!(err = ?e, "Failed to begin credential status read"); + return Err(e); + } + }; - trace!(?cse, "Begin event"); + trace!(?cse, "Begin event"); - idms_prox_read.get_credentialstatus(&cse) - }); - res + idms_prox_read.get_credentialstatus(&cse) } #[instrument( level = "info", - name = "idm_backup_code_view", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmbackupcodeview( @@ -960,45 +884,41 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let mut idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let ident = idms_prox_read - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - let target_uuid = idms_prox_read - .qs_read - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!("Error resolving id to target"); - e - })?; + let ident = idms_prox_read + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; + let target_uuid = idms_prox_read + .qs_read + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!("Error resolving id to target"); + e + })?; - // Make an event from the request - let rbce = match ReadBackupCodeEvent::from_parts( - // &idms_prox_read.qs_read, - ident, - target_uuid, - ) { - Ok(s) => s, - Err(e) => { - admin_error!("Failed to begin backup code read: {:?}", e); - return Err(e); - } - }; + // Make an event from the request + let rbce = match ReadBackupCodeEvent::from_parts( + // &idms_prox_read.qs_read, + ident, + target_uuid, + ) { + Ok(s) => s, + Err(e) => { + admin_error!("Failed to begin backup code read: {:?}", e); + return Err(e); + } + }; - trace!(?rbce, "Begin event"); + trace!(?rbce, "Begin event"); - idms_prox_read.get_backup_codes(&rbce) - }); - res + idms_prox_read.get_backup_codes(&rbce) } #[instrument( level = "info", - name = "idm_credential_update_status", - skip(self, session_token, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdatestatus( @@ -1008,29 +928,25 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_cred_update = self.idms.cred_update_transaction_async().await; - let res = spanned!("actors::v1_read::handle", { - let session_token = CredentialUpdateSessionToken { - token_enc: session_token.token, - }; + let session_token = CredentialUpdateSessionToken { + token_enc: session_token.token, + }; - idms_cred_update - .credential_update_status(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_update_status", - ); - e - }) - .map(|sta| sta.into()) - }); - res + idms_cred_update + .credential_update_status(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_update_status", + ); + e + }) + .map(|sta| sta.into()) } #[instrument( level = "info", - name = "idm_credential_update", - skip(self, session_token, scr, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdate( @@ -1041,132 +957,128 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_cred_update = self.idms.cred_update_transaction_async().await; - let res = spanned!("actors::v1_read::handle", { - let session_token = CredentialUpdateSessionToken { - token_enc: session_token.token, - }; + let session_token = CredentialUpdateSessionToken { + token_enc: session_token.token, + }; - debug!(?scr); + debug!(?scr); - match scr { - CURequest::PrimaryRemove => idms_cred_update - .credential_primary_delete(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_delete", - ); - e - }), - CURequest::Password(pw) => idms_cred_update - .credential_primary_set_password(&session_token, ct, &pw) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_set_password", - ); - e - }), - CURequest::CancelMFAReg => idms_cred_update - .credential_update_cancel_mfareg(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_update_cancel_mfareg", - ); - e - }), - CURequest::TotpGenerate => idms_cred_update - .credential_primary_init_totp(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_init_totp", - ); - e - }), - CURequest::TotpVerify(totp_chal) => idms_cred_update - .credential_primary_check_totp(&session_token, ct, totp_chal) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_check_totp", - ); - e - }), - CURequest::TotpAcceptSha1 => idms_cred_update - .credential_primary_accept_sha1_totp(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_accept_sha1_totp", - ); - e - }), - CURequest::TotpRemove => idms_cred_update - .credential_primary_remove_totp(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_remove_totp", - ); - e - }), - CURequest::BackupCodeGenerate => idms_cred_update - .credential_primary_init_backup_codes(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_init_backup_codes", - ); - e - }), - CURequest::BackupCodeRemove => idms_cred_update - .credential_primary_remove_backup_codes(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_primary_remove_backup_codes", - ); - e - }), - CURequest::PasskeyInit => idms_cred_update - .credential_passkey_init(&session_token, ct) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_passkey_init", - ); - e - }), - CURequest::PasskeyFinish(label, rpkc) => idms_cred_update - .credential_passkey_finish(&session_token, ct, label, &rpkc) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_passkey_init", - ); - e - }), - CURequest::PasskeyRemove(uuid) => idms_cred_update - .credential_passkey_remove(&session_token, ct, uuid) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin credential_passkey_init", - ); - e - }), - } - .map(|sta| sta.into()) - }); - res + match scr { + CURequest::PrimaryRemove => idms_cred_update + .credential_primary_delete(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_delete", + ); + e + }), + CURequest::Password(pw) => idms_cred_update + .credential_primary_set_password(&session_token, ct, &pw) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_set_password", + ); + e + }), + CURequest::CancelMFAReg => idms_cred_update + .credential_update_cancel_mfareg(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_update_cancel_mfareg", + ); + e + }), + CURequest::TotpGenerate => idms_cred_update + .credential_primary_init_totp(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_init_totp", + ); + e + }), + CURequest::TotpVerify(totp_chal) => idms_cred_update + .credential_primary_check_totp(&session_token, ct, totp_chal) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_check_totp", + ); + e + }), + CURequest::TotpAcceptSha1 => idms_cred_update + .credential_primary_accept_sha1_totp(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_accept_sha1_totp", + ); + e + }), + CURequest::TotpRemove => idms_cred_update + .credential_primary_remove_totp(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_remove_totp", + ); + e + }), + CURequest::BackupCodeGenerate => idms_cred_update + .credential_primary_init_backup_codes(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_init_backup_codes", + ); + e + }), + CURequest::BackupCodeRemove => idms_cred_update + .credential_primary_remove_backup_codes(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_primary_remove_backup_codes", + ); + e + }), + CURequest::PasskeyInit => idms_cred_update + .credential_passkey_init(&session_token, ct) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_passkey_init", + ); + e + }), + CURequest::PasskeyFinish(label, rpkc) => idms_cred_update + .credential_passkey_finish(&session_token, ct, label, &rpkc) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_passkey_init", + ); + e + }), + CURequest::PasskeyRemove(uuid) => idms_cred_update + .credential_passkey_remove(&session_token, ct, uuid) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin credential_passkey_init", + ); + e + }), + } + .map(|sta| sta.into()) } #[instrument( level = "info", - name = "oauth2_authorise", - skip(self, uat, auth_req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_authorise( @@ -1177,29 +1089,25 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let (ident, uat) = idms_prox_read - .validate_and_parse_uat(uat.as_deref(), ct) - .and_then(|uat| { - idms_prox_read - .process_uat_to_identity(&uat, ct) - .map(|ident| (ident, uat)) - }) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - Oauth2Error::AuthenticationRequired - })?; + let (ident, uat) = idms_prox_read + .validate_and_parse_uat(uat.as_deref(), ct) + .and_then(|uat| { + idms_prox_read + .process_uat_to_identity(&uat, ct) + .map(|ident| (ident, uat)) + }) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + Oauth2Error::AuthenticationRequired + })?; - // Now we can send to the idm server for authorisation checking. - idms_prox_read.check_oauth2_authorisation(&ident, &uat, &auth_req, ct) - }); - res + // Now we can send to the idm server for authorisation checking. + idms_prox_read.check_oauth2_authorisation(&ident, &uat, &auth_req, ct) } #[instrument( level = "info", - name = "oauth2_authorise_permit", - skip(self, uat, consent_req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_authorise_permit( @@ -1210,28 +1118,24 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let (ident, uat) = idms_prox_read - .validate_and_parse_uat(uat.as_deref(), ct) - .and_then(|uat| { - idms_prox_read - .process_uat_to_identity(&uat, ct) - .map(|ident| (ident, uat)) - }) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let (ident, uat) = idms_prox_read + .validate_and_parse_uat(uat.as_deref(), ct) + .and_then(|uat| { + idms_prox_read + .process_uat_to_identity(&uat, ct) + .map(|ident| (ident, uat)) + }) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - idms_prox_read.check_oauth2_authorise_permit(&ident, &uat, &consent_req, ct) - }); - res + idms_prox_read.check_oauth2_authorise_permit(&ident, &uat, &consent_req, ct) } #[instrument( level = "info", - name = "oauth2_authorise_reject", - skip(self, uat, consent_req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_authorise_reject( @@ -1242,28 +1146,24 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - let (ident, uat) = idms_prox_read - .validate_and_parse_uat(uat.as_deref(), ct) - .and_then(|uat| { - idms_prox_read - .process_uat_to_identity(&uat, ct) - .map(|ident| (ident, uat)) - }) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; + let (ident, uat) = idms_prox_read + .validate_and_parse_uat(uat.as_deref(), ct) + .and_then(|uat| { + idms_prox_read + .process_uat_to_identity(&uat, ct) + .map(|ident| (ident, uat)) + }) + .map_err(|e| { + admin_error!("Invalid identity: {:?}", e); + e + })?; - idms_prox_read.check_oauth2_authorise_reject(&ident, &uat, &consent_req, ct) - }); - res + idms_prox_read.check_oauth2_authorise_reject(&ident, &uat, &consent_req, ct) } #[instrument( level = "info", - name = "oauth2_token_exchange", - skip(self, client_authz, token_req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_token_exchange( @@ -1274,17 +1174,13 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - // Now we can send to the idm server for authorisation checking. - idms_prox_read.check_oauth2_token_exchange(client_authz.as_deref(), &token_req, ct) - }); - res + // Now we can send to the idm server for authorisation checking. + idms_prox_read.check_oauth2_token_exchange(client_authz.as_deref(), &token_req, ct) } #[instrument( level = "info", - name = "oauth2_token_introspect", - skip(self, client_authz, intr_req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_token_introspect( @@ -1295,17 +1191,13 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - // Now we can send to the idm server for introspection checking. - idms_prox_read.check_oauth2_token_introspect(&client_authz, &intr_req, ct) - }); - res + // Now we can send to the idm server for introspection checking. + idms_prox_read.check_oauth2_token_introspect(&client_authz, &intr_req, ct) } #[instrument( level = "info", - name = "oauth2_openid_userinfo", - skip(self, client_id, client_authz, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_openid_userinfo( @@ -1316,16 +1208,12 @@ impl QueryServerReadV1 { ) -> Result { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - idms_prox_read.oauth2_openid_userinfo(&client_id, &client_authz, ct) - }); - res + idms_prox_read.oauth2_openid_userinfo(&client_id, &client_authz, ct) } #[instrument( level = "info", - name = "oauth2_openid_discovery", - skip(self, client_id, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_openid_discovery( @@ -1334,16 +1222,12 @@ impl QueryServerReadV1 { eventid: Uuid, ) -> Result { let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - idms_prox_read.oauth2_openid_discovery(&client_id) - }); - res + idms_prox_read.oauth2_openid_discovery(&client_id) } #[instrument( level = "info", - name = "oauth2_openid_publickey", - skip(self, client_id, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_openid_publickey( @@ -1352,30 +1236,22 @@ impl QueryServerReadV1 { eventid: Uuid, ) -> Result { let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - idms_prox_read.oauth2_openid_publickey(&client_id) - }); - res + idms_prox_read.oauth2_openid_publickey(&client_id) } #[instrument( level = "info", - name = "get_domain_display_name", - skip(self, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn get_domain_display_name(&self, eventid: Uuid) -> String { let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - idms_prox_read.qs_read.get_domain_display_name().to_string() - }); - res + idms_prox_read.qs_read.get_domain_display_name().to_string() } #[instrument( level = "info", - name = "auth_valid", - skip(self, uat, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_auth_valid( @@ -1386,22 +1262,18 @@ impl QueryServerReadV1 { let ct = duration_from_epoch_now(); let idms_prox_read = self.idms.proxy_read_async().await; - let res = spanned!("actors::v1_read::handle", { - idms_prox_read - .validate_and_parse_uat(uat.as_deref(), ct) - .map(|_| ()) - .map_err(|e| { - admin_error!("Invalid token: {:?}", e); - e - }) - }); - res + idms_prox_read + .validate_and_parse_uat(uat.as_deref(), ct) + .map(|_| ()) + .map_err(|e| { + admin_error!("Invalid token: {:?}", e); + e + }) } #[instrument( level = "info", - name = "ldap_request", - skip(self, eventid, protomsg, uat) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_ldaprequest( @@ -1410,7 +1282,6 @@ impl QueryServerReadV1 { protomsg: LdapMsg, uat: Option, ) -> Option { - // let res = spanned!( "actors::v1_read::handle", { let res = match ServerOps::try_from(protomsg) { Ok(server_op) => self .ldap @@ -1428,7 +1299,6 @@ impl QueryServerReadV1 { format!("Invalid Request {:?}", &eventid).as_str(), )), }; - // }); Some(res) } } diff --git a/kanidmd/idm/src/actors/v1_write.rs b/kanidmd/idm/src/actors/v1_write.rs index 7a17cc096..ce17fedef 100644 --- a/kanidmd/idm/src/actors/v1_write.rs +++ b/kanidmd/idm/src/actors/v1_write.rs @@ -1,43 +1,35 @@ use std::iter; use std::sync::Arc; use std::time::Duration; -use tracing::{info, instrument, span, trace, Level}; -use crate::prelude::*; - -use crate::idm::credupdatesession::{ - CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent, - InitCredentialUpdateIntentEvent, +use kanidm_proto::v1::{ + AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest, + Entry as ProtoEntry, GroupUnixExtend, Modify as ProtoModify, ModifyList as ProtoModifyList, + ModifyRequest, OperationError, }; +use time::OffsetDateTime; +use tracing::{info, instrument, span, trace, Level}; +use uuid::Uuid; use crate::event::{ CreateEvent, DeleteEvent, ModifyEvent, PurgeRecycledEvent, PurgeTombstoneEvent, ReviveRecycledEvent, }; +use crate::filter::{Filter, FilterInvalid}; +use crate::idm::credupdatesession::{ + CredentialUpdateIntentToken, CredentialUpdateSessionToken, InitCredentialUpdateEvent, + InitCredentialUpdateIntentEvent, +}; +use crate::idm::delayed::DelayedAction; use crate::idm::event::{ GeneratePasswordEvent, RegenerateRadiusSecretEvent, UnixPasswordChangeEvent, }; -use crate::modify::{Modify, ModifyInvalid, ModifyList}; -use crate::value::{PartialValue, Value}; -use kanidm_proto::v1::OperationError; - -use crate::filter::{Filter, FilterInvalid}; -use crate::idm::delayed::DelayedAction; use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::serviceaccount::{DestroyApiTokenEvent, GenerateApiTokenEvent}; +use crate::modify::{Modify, ModifyInvalid, ModifyList}; +use crate::prelude::*; use crate::utils::duration_from_epoch_now; - -use kanidm_proto::v1::Entry as ProtoEntry; -use kanidm_proto::v1::Modify as ProtoModify; -use kanidm_proto::v1::ModifyList as ProtoModifyList; -use kanidm_proto::v1::{ - AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest, - GroupUnixExtend, ModifyRequest, -}; - -use time::OffsetDateTime; - -use uuid::Uuid; +use crate::value::{PartialValue, Value}; pub struct QueryServerWriteV1 { _log_level: Option, @@ -63,6 +55,7 @@ impl QueryServerWriteV1 { &(*x_ptr) } + #[instrument(level = "debug", skip_all)] async fn modify_from_parts( &self, uat: Option, @@ -71,47 +64,46 @@ impl QueryServerWriteV1 { filter: Filter, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("modify_from_parts", { - let ct = duration_from_epoch_now(); + let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - let mdf = match ModifyEvent::from_parts( - ident, - target_uuid, - proto_ml, - filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err=?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_parts( + ident, + target_uuid, + proto_ml, + filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err=?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } + #[instrument(level = "debug", skip_all)] async fn modify_from_internal_parts( &self, uat: Option, @@ -120,54 +112,51 @@ impl QueryServerWriteV1 { filter: Filter, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("modify_from_internal_parts", { - let ct = duration_from_epoch_now(); + let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name) - .map_err(|e| { - admin_error!("Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name) + .map_err(|e| { + admin_error!("Error resolving id to target"); + e + })?; - let f_uuid = filter_all!(f_eq("uuid", PartialValue::new_uuid(target_uuid))); - // Add any supplemental conditions we have. - let joined_filter = Filter::join_parts_and(f_uuid, filter); + let f_uuid = filter_all!(f_eq("uuid", PartialValue::new_uuid(target_uuid))); + // Add any supplemental conditions we have. + let joined_filter = Filter::join_parts_and(f_uuid, filter); - let mdf = match ModifyEvent::from_internal_parts( - ident, - ml, - &joined_filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_internal_parts( + ident, + ml, + &joined_filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( level = "info", - name = "create", - skip(self, uat, req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_create( @@ -177,39 +166,34 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); + let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let crt = match CreateEvent::from_message(ident, &req, &idms_prox_write.qs_write) { - Ok(c) => c, - Err(e) => { - admin_warn!(err = ?e, "Failed to begin create"); - return Err(e); - } - }; + let crt = match CreateEvent::from_message(ident, &req, &idms_prox_write.qs_write) { + Ok(c) => c, + Err(e) => { + admin_warn!(err = ?e, "Failed to begin create"); + return Err(e); + } + }; - trace!(?crt, "Begin create event"); + trace!(?crt, "Begin create event"); - idms_prox_write - .qs_write - .create(&crt) - .and_then(|_| idms_prox_write.commit()) - }); - // At the end of the event we send it for logging. - res + idms_prox_write + .qs_write + .create(&crt) + .and_then(|_| idms_prox_write.commit()) } #[instrument( level = "info", - name = "modify", - skip(self, uat, req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_modify( @@ -219,37 +203,33 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let mdf = match ModifyEvent::from_message(ident, &req, &idms_prox_write.qs_write) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_message(ident, &req, &idms_prox_write.qs_write) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit()) - }); - res + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit()) } #[instrument( level = "info", - name = "delete", - skip(self, uat, req, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_delete( @@ -259,36 +239,32 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let del = match DeleteEvent::from_message(ident, &req, &idms_prox_write.qs_write) { - Ok(d) => d, - Err(e) => { - admin_error!(err = ?e, "Failed to begin delete"); - return Err(e); - } - }; + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let del = match DeleteEvent::from_message(ident, &req, &idms_prox_write.qs_write) { + Ok(d) => d, + Err(e) => { + admin_error!(err = ?e, "Failed to begin delete"); + return Err(e); + } + }; - trace!(?del, "Begin delete event"); + trace!(?del, "Begin delete event"); - idms_prox_write - .qs_write - .delete(&del) - .and_then(|_| idms_prox_write.commit()) - }); - res + idms_prox_write + .qs_write + .delete(&del) + .and_then(|_| idms_prox_write.commit()) } #[instrument( level = "info", - name = "patch", - skip(self, uat, filter, update, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internalpatch( @@ -300,47 +276,38 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { // Given a protoEntry, turn this into a modification set. let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - - // Transform the ProtoEntry to a Modlist - let modlist = - ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| { - admin_error!(err = ?e, "Invalid Patch Request"); - e - })?; - - let mdf = ModifyEvent::from_internal_parts( - ident, - &modlist, - &filter, - &idms_prox_write.qs_write, - ) + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + + // Transform the ProtoEntry to a Modlist + let modlist = ModifyList::from_patch(&update, &idms_prox_write.qs_write).map_err(|e| { + admin_error!(err = ?e, "Invalid Patch Request"); + e + })?; + + let mdf = + ModifyEvent::from_internal_parts(ident, &modlist, &filter, &idms_prox_write.qs_write) + .map_err(|e| { admin_error!(err = ?e, "Failed to begin modify"); e })?; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit()) - }); - res.map(|_| ()) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit()) } #[instrument( level = "info", - name = "delete2", - skip(self, uat, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_internaldelete( @@ -350,36 +317,32 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let del = match DeleteEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) { - Ok(d) => d, - Err(e) => { - admin_error!(err = ?e, "Failed to begin delete"); - return Err(e); - } - }; + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let del = match DeleteEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) { + Ok(d) => d, + Err(e) => { + admin_error!(err = ?e, "Failed to begin delete"); + return Err(e); + } + }; - trace!(?del, "Begin delete event"); + trace!(?del, "Begin delete event"); - idms_prox_write - .qs_write - .delete(&del) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }); - res + idms_prox_write + .qs_write + .delete(&del) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( level = "info", - name = "revive_recycled", - skip(self, uat, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_reviverecycled( @@ -389,37 +352,32 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - let res = spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let rev = - match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) { - Ok(r) => r, - Err(e) => { - admin_error!(err = ?e, "Failed to begin revive"); - return Err(e); - } - }; + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let rev = match ReviveRecycledEvent::from_parts(ident, &filter, &idms_prox_write.qs_write) { + Ok(r) => r, + Err(e) => { + admin_error!(err = ?e, "Failed to begin revive"); + return Err(e); + } + }; - trace!(?rev, "Begin revive event"); + trace!(?rev, "Begin revive event"); - idms_prox_write - .qs_write - .revive_recycled(&rev) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }); - res + idms_prox_write + .qs_write + .revive_recycled(&rev) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( level = "info", - name = "service_account_credential_generate", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_service_account_credential_generate( @@ -430,45 +388,41 @@ impl QueryServerWriteV1 { ) -> Result { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - - // given the uuid_or_name, determine the target uuid. - // We can either do this by trying to parse the name or by creating a filter - // to find the entry - there are risks to both TBH ... especially when the uuid - // is also an entries name, but that they aren't the same entry. - - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; - - let gpe = GeneratePasswordEvent::from_parts(ident, target_uuid).map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin handle_service_account_credential_generate", - ); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); e })?; - idms_prox_write - .generate_account_password(&gpe) - .and_then(|r| idms_prox_write.commit().map(|_| r)) - }); - res + + // given the uuid_or_name, determine the target uuid. + // We can either do this by trying to parse the name or by creating a filter + // to find the entry - there are risks to both TBH ... especially when the uuid + // is also an entries name, but that they aren't the same entry. + + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; + + let gpe = GeneratePasswordEvent::from_parts(ident, target_uuid).map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin handle_service_account_credential_generate", + ); + e + })?; + idms_prox_write + .generate_account_password(&gpe) + .and_then(|r| idms_prox_write.commit().map(|_| r)) } #[instrument( level = "info", - name = "service_account_credential_generate", - skip(self, uat, uuid_or_name, label, expiry, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_service_account_api_token_generate( @@ -510,7 +464,6 @@ impl QueryServerWriteV1 { #[instrument( level = "info", - name = "service_account_credential_generate", skip_all, fields(uuid = ?eventid) )] @@ -551,8 +504,7 @@ impl QueryServerWriteV1 { #[instrument( level = "info", - name = "idm_credential_update", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdate( @@ -563,48 +515,44 @@ impl QueryServerWriteV1 { ) -> Result<(CUSessionToken, CUStatus), OperationError> { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - idms_prox_write - .init_credential_update(&InitCredentialUpdateEvent::new(ident, target_uuid), ct) - .and_then(|tok| idms_prox_write.commit().map(|_| tok)) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin init_credential_update", - ); - e - }) - .map(|(tok, sta)| { - ( - CUSessionToken { - token: tok.token_enc, - }, - sta.into(), - ) - }) - }); - res + idms_prox_write + .init_credential_update(&InitCredentialUpdateEvent::new(ident, target_uuid), ct) + .and_then(|tok| idms_prox_write.commit().map(|_| tok)) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin init_credential_update", + ); + e + }) + .map(|(tok, sta)| { + ( + CUSessionToken { + token: tok.token_enc, + }, + sta.into(), + ) + }) } #[instrument( level = "info", - name = "idm_credential_update_intent", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdateintent( @@ -616,46 +564,42 @@ impl QueryServerWriteV1 { ) -> Result { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - idms_prox_write - .init_credential_update_intent( - &InitCredentialUpdateIntentEvent::new(ident, target_uuid, ttl), - ct, - ) - .and_then(|tok| idms_prox_write.commit().map(|_| tok)) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin init_credential_update_intent", - ); - e - }) - .map(|tok| CUIntentToken { - token: tok.intent_id, - }) - }); - res + idms_prox_write + .init_credential_update_intent( + &InitCredentialUpdateIntentEvent::new(ident, target_uuid, ttl), + ct, + ) + .and_then(|tok| idms_prox_write.commit().map(|_| tok)) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin init_credential_update_intent", + ); + e + }) + .map(|tok| CUIntentToken { + token: tok.intent_id, + }) } #[instrument( level = "info", - name = "idm_credential_exchange_intent", - skip(self, intent_token, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialexchangeintent( @@ -665,37 +609,33 @@ impl QueryServerWriteV1 { ) -> Result<(CUSessionToken, CUStatus), OperationError> { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let intent_token = CredentialUpdateIntentToken { - intent_id: intent_token.token, - }; - // TODO: this is throwing a 500 error when a session is already in use, that seems bad? - idms_prox_write - .exchange_intent_credential_update(intent_token, ct) - .and_then(|tok| idms_prox_write.commit().map(|_| tok)) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin exchange_intent_credential_update", - ); - e - }) - .map(|(tok, sta)| { - ( - CUSessionToken { - token: tok.token_enc, - }, - sta.into(), - ) - }) - }); - res + let intent_token = CredentialUpdateIntentToken { + intent_id: intent_token.token, + }; + // TODO: this is throwing a 500 error when a session is already in use, that seems bad? + idms_prox_write + .exchange_intent_credential_update(intent_token, ct) + .and_then(|tok| idms_prox_write.commit().map(|_| tok)) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin exchange_intent_credential_update", + ); + e + }) + .map(|(tok, sta)| { + ( + CUSessionToken { + token: tok.token_enc, + }, + sta.into(), + ) + }) } #[instrument( level = "info", - name = "idm_credential_update_commit", - skip(self, session_token, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdatecommit( @@ -705,29 +645,25 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let session_token = CredentialUpdateSessionToken { - token_enc: session_token.token, - }; + let session_token = CredentialUpdateSessionToken { + token_enc: session_token.token, + }; - idms_prox_write - .commit_credential_update(&session_token, ct) - .and_then(|tok| idms_prox_write.commit().map(|_| tok)) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin commit_credential_update", - ); - e - }) - }); - res + idms_prox_write + .commit_credential_update(&session_token, ct) + .and_then(|tok| idms_prox_write.commit().map(|_| tok)) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin commit_credential_update", + ); + e + }) } #[instrument( level = "info", - name = "idm_credential_update_cancel", - skip(self, session_token, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmcredentialupdatecancel( @@ -737,29 +673,25 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let session_token = CredentialUpdateSessionToken { - token_enc: session_token.token, - }; + let session_token = CredentialUpdateSessionToken { + token_enc: session_token.token, + }; - idms_prox_write - .cancel_credential_update(&session_token, ct) - .and_then(|tok| idms_prox_write.commit().map(|_| tok)) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin commit_credential_cancel", - ); - e - }) - }); - res + idms_prox_write + .cancel_credential_update(&session_token, ct) + .and_then(|tok| idms_prox_write.commit().map(|_| tok)) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin commit_credential_cancel", + ); + e + }) } #[instrument( level = "info", - name = "handle_service_account_into_person", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_service_account_into_person( @@ -770,32 +702,28 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { let ct = duration_from_epoch_now(); let idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - idms_prox_write - .service_account_into_person(&ident, target_uuid) - .and_then(|_| idms_prox_write.commit()) - }); - res + idms_prox_write + .service_account_into_person(&ident, target_uuid) + .and_then(|_| idms_prox_write.commit()) } #[instrument( level = "info", - name = "regenerate_radius_secret", - skip(self, uat, uuid_or_name, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_regenerateradius( @@ -806,49 +734,42 @@ impl QueryServerWriteV1 { ) -> Result { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!( - "actors::v1_write::handle", - { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - let rrse = RegenerateRadiusSecretEvent::from_parts( - // &idms_prox_write.qs_write, - ident, - target_uuid, - ) - .map_err(|e| { - admin_error!( - err = ?e, - "Failed to begin idm_account_regenerate_radius", - ); - e - })?; + let rrse = RegenerateRadiusSecretEvent::from_parts( + // &idms_prox_write.qs_write, + ident, + target_uuid, + ) + .map_err(|e| { + admin_error!( + err = ?e, + "Failed to begin idm_account_regenerate_radius", + ); + e + })?; - idms_prox_write - .regenerate_radius_secret(&rrse) - .and_then(|r| idms_prox_write.commit().map(|_| r)) - } - ); - res + idms_prox_write + .regenerate_radius_secret(&rrse) + .and_then(|r| idms_prox_write.commit().map(|_| r)) } #[instrument( level = "info", - name = "purge_attribute", - skip(self, uat, uuid_or_name, attr, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_purgeattribute( @@ -861,48 +782,45 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { let ct = duration_from_epoch_now(); let idms_prox_write = self.idms.proxy_write_async(ct).await; - spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - let mdf = match ModifyEvent::from_target_uuid_attr_purge( - ident, - target_uuid, - &attr, - filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_target_uuid_attr_purge( + ident, + target_uuid, + &attr, + filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( level = "info", - name = "remove_attribute_values", - skip(self, uat, uuid_or_name, attr, values, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_removeattributevalues( @@ -915,50 +833,48 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("actors::v1_write::handle", { - let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - let target_uuid = idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving id to target"); - e - })?; + let ct = duration_from_epoch_now(); + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; + let target_uuid = idms_prox_write + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving id to target"); + e + })?; - let proto_ml = ProtoModifyList::new_list( - values - .into_iter() - .map(|v| ProtoModify::Removed(attr.clone(), v)) - .collect(), - ); + let proto_ml = ProtoModifyList::new_list( + values + .into_iter() + .map(|v| ProtoModify::Removed(attr.clone(), v)) + .collect(), + ); - let mdf = match ModifyEvent::from_parts( - ident, - target_uuid, - &proto_ml, - filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_parts( + ident, + target_uuid, + &proto_ml, + filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( @@ -1121,8 +1037,7 @@ impl QueryServerWriteV1 { #[instrument( level = "info", - name = "idm_account_unix_set_cred", - skip(self, uat, uuid_or_name, cred, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_idmaccountunixsetcred( @@ -1134,46 +1049,42 @@ impl QueryServerWriteV1 { ) -> Result<(), OperationError> { let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - let res = spanned!("actors::v1_write::handle", { - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; - - let target_uuid = Uuid::parse_str(uuid_or_name.as_str()).or_else(|_| { - idms_prox_write - .qs_write - .name_to_uuid(uuid_or_name.as_str()) - .map_err(|e| { - admin_info!("Error resolving as gidnumber continuing ..."); - e - }) - })?; - - let upce = UnixPasswordChangeEvent::from_parts( - // &idms_prox_write.qs_write, - ident, - target_uuid, - cred, - ) + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) .map_err(|e| { - admin_error!(err = ?e, "Failed to begin UnixPasswordChangeEvent"); + admin_error!(err = ?e, "Invalid identity"); e })?; + + let target_uuid = Uuid::parse_str(uuid_or_name.as_str()).or_else(|_| { idms_prox_write - .set_unix_account_password(&upce) - .and_then(|_| idms_prox_write.commit()) - .map(|_| ()) - }); - res + .qs_write + .name_to_uuid(uuid_or_name.as_str()) + .map_err(|e| { + admin_info!("Error resolving as gidnumber continuing ..."); + e + }) + })?; + + let upce = UnixPasswordChangeEvent::from_parts( + // &idms_prox_write.qs_write, + ident, + target_uuid, + cred, + ) + .map_err(|e| { + admin_error!(err = ?e, "Failed to begin UnixPasswordChangeEvent"); + e + })?; + idms_prox_write + .set_unix_account_password(&upce) + .and_then(|_| idms_prox_write.commit()) + .map(|_| ()) } #[instrument( level = "info", - name = "oauth2_scopemap_create", - skip(self, uat, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_scopemap_create( @@ -1187,61 +1098,54 @@ impl QueryServerWriteV1 { // Because this is from internal, we can generate a real modlist, rather // than relying on the proto ones. let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("handle_oauth2_scopemap_create", { - let ct = duration_from_epoch_now(); + let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let group_uuid = idms_prox_write - .qs_write - .name_to_uuid(group.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving group name to target"); - e - })?; + let group_uuid = idms_prox_write + .qs_write + .name_to_uuid(group.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving group name to target"); + e + })?; - let ml = ModifyList::new_append( - "oauth2_rs_scope_map", - Value::new_oauthscopemap(group_uuid, scopes.into_iter().collect()).ok_or_else( - || { - OperationError::InvalidAttribute( - "Invalid Oauth Scope Map syntax".to_string(), - ) - }, - )?, - ); + let ml = ModifyList::new_append( + "oauth2_rs_scope_map", + Value::new_oauthscopemap(group_uuid, scopes.into_iter().collect()).ok_or_else( + || OperationError::InvalidAttribute("Invalid Oauth Scope Map syntax".to_string()), + )?, + ); - let mdf = match ModifyEvent::from_internal_parts( - ident, - &ml, - &filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_internal_parts( + ident, + &ml, + &filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } #[instrument( level = "info", - name = "oauth2_scopemap_delete", - skip(self, uat, filter, eventid) + skip_all, fields(uuid = ?eventid) )] pub async fn handle_oauth2_scopemap_delete( @@ -1252,88 +1156,80 @@ impl QueryServerWriteV1 { eventid: Uuid, ) -> Result<(), OperationError> { let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("handle_oauth2_scopemap_create", { - let ct = duration_from_epoch_now(); + let ct = duration_from_epoch_now(); - let ident = idms_prox_write - .validate_and_parse_token_to_ident(uat.as_deref(), ct) - .map_err(|e| { - admin_error!(err = ?e, "Invalid identity"); - e - })?; + let ident = idms_prox_write + .validate_and_parse_token_to_ident(uat.as_deref(), ct) + .map_err(|e| { + admin_error!(err = ?e, "Invalid identity"); + e + })?; - let group_uuid = idms_prox_write - .qs_write - .name_to_uuid(group.as_str()) - .map_err(|e| { - admin_error!(err = ?e, "Error resolving group name to target"); - e - })?; + let group_uuid = idms_prox_write + .qs_write + .name_to_uuid(group.as_str()) + .map_err(|e| { + admin_error!(err = ?e, "Error resolving group name to target"); + e + })?; - let ml = ModifyList::new_remove("oauth2_rs_scope_map", PartialValue::Refer(group_uuid)); + let ml = ModifyList::new_remove("oauth2_rs_scope_map", PartialValue::Refer(group_uuid)); - let mdf = match ModifyEvent::from_internal_parts( - ident, - &ml, - &filter, - &idms_prox_write.qs_write, - ) { - Ok(m) => m, - Err(e) => { - admin_error!(err = ?e, "Failed to begin modify"); - return Err(e); - } - }; + let mdf = match ModifyEvent::from_internal_parts( + ident, + &ml, + &filter, + &idms_prox_write.qs_write, + ) { + Ok(m) => m, + Err(e) => { + admin_error!(err = ?e, "Failed to begin modify"); + return Err(e); + } + }; - trace!(?mdf, "Begin modify event"); + trace!(?mdf, "Begin modify event"); - idms_prox_write - .qs_write - .modify(&mdf) - .and_then(|_| idms_prox_write.commit().map(|_| ())) - }) + idms_prox_write + .qs_write + .modify(&mdf) + .and_then(|_| idms_prox_write.commit().map(|_| ())) } // ===== These below are internal only event types. ===== #[instrument( level = "info", - name = "purge_tombstone_event", - skip(self, msg) + skip_all, fields(uuid = ?msg.eventid) )] pub(crate) async fn handle_purgetombstoneevent(&self, msg: PurgeTombstoneEvent) { trace!(?msg, "Begin purge tombstone event"); let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("actors::v1_write::handle", { - let res = idms_prox_write - .qs_write - .purge_tombstones() - .and_then(|_| idms_prox_write.commit()); - admin_info!(?res, "Purge tombstones result"); - #[allow(clippy::expect_used)] - res.expect("Invalid Server State"); - }); + let res = idms_prox_write + .qs_write + .purge_tombstones() + .and_then(|_| idms_prox_write.commit()); + admin_info!(?res, "Purge tombstones result"); + #[allow(clippy::expect_used)] + res.expect("Invalid Server State"); } #[instrument( level = "info", - name = "purge_recycled_event", - skip(self, msg) + skip_all, fields(uuid = ?msg.eventid) )] pub(crate) async fn handle_purgerecycledevent(&self, msg: PurgeRecycledEvent) { trace!(?msg, "Begin purge recycled event"); let idms_prox_write = self.idms.proxy_write_async(duration_from_epoch_now()).await; - spanned!("actors::v1_write::handle", { - let res = idms_prox_write - .qs_write - .purge_recycled() - .and_then(|_| idms_prox_write.commit()); - admin_info!(?res, "Purge recycled result"); - #[allow(clippy::expect_used)] - res.expect("Invalid Server State"); - }); + let res = idms_prox_write + .qs_write + .purge_recycled() + .and_then(|_| idms_prox_write.commit()); + admin_info!(?res, "Purge recycled result"); + #[allow(clippy::expect_used)] + res.expect("Invalid Server State"); } pub(crate) async fn handle_delayedaction(&self, da: DelayedAction) { @@ -1344,13 +1240,11 @@ impl QueryServerWriteV1 { trace!("Begin delayed action ..."); let ct = duration_from_epoch_now(); let mut idms_prox_write = self.idms.proxy_write_async(ct).await; - spanned!("actors::v1_write::handle", { - if let Err(res) = idms_prox_write - .process_delayedaction(da) - .and_then(|_| idms_prox_write.commit()) - { - admin_info!(?res, "delayed action error"); - } - }); + if let Err(res) = idms_prox_write + .process_delayedaction(da) + .and_then(|_| idms_prox_write.commit()) + { + admin_info!(?res, "delayed action error"); + } } } diff --git a/kanidmd/idm/src/audit.rs b/kanidmd/idm/src/audit.rs index 89435428e..ee7f1661b 100644 --- a/kanidmd/idm/src/audit.rs +++ b/kanidmd/idm/src/audit.rs @@ -1,6 +1,7 @@ -use serde::{Deserialize, Serialize}; use std::fmt; +use serde::{Deserialize, Serialize}; + include!("./audit_loglevel.rs"); pub const AUDIT_LINE_SIZE: usize = 512; diff --git a/kanidmd/idm/src/be/dbentry.rs b/kanidmd/idm/src/be/dbentry.rs index ec438bd50..f29c3440c 100644 --- a/kanidmd/idm/src/be/dbentry.rs +++ b/kanidmd/idm/src/be/dbentry.rs @@ -1,11 +1,13 @@ -use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1}; -use crate::prelude::OperationError; -use serde::{Deserialize, Serialize}; -use smartstring::alias::String as AttrString; use std::collections::BTreeMap; use std::time::Duration; + +use serde::{Deserialize, Serialize}; +use smartstring::alias::String as AttrString; use uuid::Uuid; +use crate::be::dbvalue::{DbValueEmailAddressV1, DbValuePhoneNumberV1, DbValueSetV2, DbValueV1}; +use crate::prelude::OperationError; + #[derive(Serialize, Deserialize, Debug)] pub struct DbEntryV1 { pub attrs: BTreeMap>, diff --git a/kanidmd/idm/src/be/dbvalue.rs b/kanidmd/idm/src/be/dbvalue.rs index 76f8eba9d..c2c681750 100644 --- a/kanidmd/idm/src/be/dbvalue.rs +++ b/kanidmd/idm/src/be/dbvalue.rs @@ -1,15 +1,15 @@ -use hashbrown::HashSet; -use serde::{Deserialize, Serialize}; use std::fmt; use std::time::Duration; + +use hashbrown::HashSet; +use serde::{Deserialize, Serialize}; use url::Url; use uuid::Uuid; +use webauthn_rs::prelude::{ + DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, SecurityKey as SecurityKeyV4, +}; use webauthn_rs_core::proto::{COSEKey, UserVerificationPolicy}; -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; -use webauthn_rs::prelude::SecurityKey as SecurityKeyV4; - #[derive(Serialize, Deserialize, Debug)] pub struct DbCidV1 { #[serde(rename = "d")] @@ -556,11 +556,11 @@ impl DbValueSetV2 { #[cfg(test)] mod tests { - use super::DbCred; - use super::{DbBackupCodeV1, DbPasswordV1, DbTotpV1, DbWebauthnV1}; use serde::{Deserialize, Serialize}; use uuid::Uuid; + use super::{DbBackupCodeV1, DbCred, DbPasswordV1, DbTotpV1, DbWebauthnV1}; + fn dbcred_type_default_pw() -> DbCredTypeV1 { DbCredTypeV1::Pw } diff --git a/kanidmd/idm/src/be/idl_arc_sqlite.rs b/kanidmd/idm/src/be/idl_arc_sqlite.rs index 6d71049d1..1483c3683 100644 --- a/kanidmd/idm/src/be/idl_arc_sqlite.rs +++ b/kanidmd/idm/src/be/idl_arc_sqlite.rs @@ -1,3 +1,18 @@ +use std::collections::BTreeSet; +use std::convert::TryInto; +use std::ops::DerefMut; +use std::sync::Arc; +use std::time::Duration; + +use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn, ARCacheWriteTxn}; +use concread::cowcell::*; +use hashbrown::HashMap; +use idlset::v2::IDLBitRange; +use idlset::AndNot; +use kanidm_proto::v1::{ConsistencyError, OperationError}; +use tracing::trace; +use uuid::Uuid; + use crate::be::idl_sqlite::{ IdlSqlite, IdlSqliteReadTransaction, IdlSqliteTransaction, IdlSqliteWriteTransaction, }; @@ -6,24 +21,8 @@ use crate::be::idxkey::{ }; use crate::be::{BackendConfig, IdList, IdRawEntry}; use crate::entry::{Entry, EntryCommitted, EntrySealed}; -use crate::value::IndexType; -use crate::value::Value; - -use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn, ARCacheWriteTxn}; -use concread::cowcell::*; -use idlset::{v2::IDLBitRange, AndNot}; -use kanidm_proto::v1::{ConsistencyError, OperationError}; - -use hashbrown::HashMap; -use std::collections::BTreeSet; -use std::convert::TryInto; -use std::ops::DerefMut; -use std::sync::Arc; -use std::time::Duration; -use uuid::Uuid; - use crate::prelude::*; -use tracing::trace; +use crate::value::{IndexType, Value}; // use std::borrow::Borrow; @@ -82,58 +81,56 @@ macro_rules! get_identry { $idl:expr, $is_read_op:expr ) => {{ - spanned!("be::idl_arc_sqlite::get_identry", { - let mut result: Vec> = Vec::new(); - match $idl { - IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => { - let mut nidl = IDLBitRange::new(); + let mut result: Vec> = Vec::new(); + match $idl { + IdList::Partial(idli) | IdList::PartialThreshold(idli) | IdList::Indexed(idli) => { + let mut nidl = IDLBitRange::new(); - idli.into_iter().for_each(|i| { - // For all the id's in idl. - // is it in the cache? - match $self.entry_cache.get(&i) { - Some(eref) => result.push(eref.clone()), - None => unsafe { nidl.push_id(i) }, - } + idli.into_iter().for_each(|i| { + // For all the id's in idl. + // is it in the cache? + match $self.entry_cache.get(&i) { + Some(eref) => result.push(eref.clone()), + None => unsafe { nidl.push_id(i) }, + } + }); + + if !nidl.is_empty() { + // Now, get anything from nidl that is needed. + let mut db_result = $self.db.get_identry(&IdList::Partial(nidl))?; + // Clone everything from db_result into the cache. + if $is_read_op { + db_result.iter().for_each(|e| { + $self.entry_cache.insert(e.get_id(), e.clone()); + }); + } + // Merge the two vecs + result.append(&mut db_result); + } + } + IdList::AllIds => { + // VERY similar to above, but we skip adding the entries to the cache + // on miss to prevent scan/invalidation attacks. + let idli = (*$self.allids).clone(); + let mut nidl = IDLBitRange::new(); + + (&idli) + .into_iter() + .for_each(|i| match $self.entry_cache.get(&i) { + Some(eref) => result.push(eref.clone()), + None => unsafe { nidl.push_id(i) }, }); - if !nidl.is_empty() { - // Now, get anything from nidl that is needed. - let mut db_result = $self.db.get_identry(&IdList::Partial(nidl))?; - // Clone everything from db_result into the cache. - if $is_read_op { - db_result.iter().for_each(|e| { - $self.entry_cache.insert(e.get_id(), e.clone()); - }); - } - // Merge the two vecs - result.append(&mut db_result); - } + if !nidl.is_empty() { + // Now, get anything from nidl that is needed. + let mut db_result = $self.db.get_identry(&IdList::Partial(nidl))?; + // Merge the two vecs + result.append(&mut db_result); } - IdList::AllIds => { - // VERY similar to above, but we skip adding the entries to the cache - // on miss to prevent scan/invalidation attacks. - let idli = (*$self.allids).clone(); - let mut nidl = IDLBitRange::new(); - - (&idli) - .into_iter() - .for_each(|i| match $self.entry_cache.get(&i) { - Some(eref) => result.push(eref.clone()), - None => unsafe { nidl.push_id(i) }, - }); - - if !nidl.is_empty() { - // Now, get anything from nidl that is needed. - let mut db_result = $self.db.get_identry(&IdList::Partial(nidl))?; - // Merge the two vecs - result.append(&mut db_result); - } - } - }; - // Return - Ok(result) - }) + } + }; + // Return + Ok(result) }}; } @@ -165,7 +162,6 @@ macro_rules! get_idl { $itype:expr, $idx_key:expr ) => {{ - spanned!("be::idl_arc_sqlite::get_idl", { // SEE ALSO #259: Find a way to implement borrow for this properly. // I don't think this is possible. When we make this dyn, the arc // needs the dyn trait to be sized so that it *could* claim a clone @@ -188,10 +184,9 @@ macro_rules! get_idl { // If hit, continue. if let Some(ref data) = cache_r { trace!( - %data, - "Got cached idl for index {:?} {:?}", - $itype, - $attr, + cached_index = ?$itype, + attr = ?$attr, + idl = %data, ); return Ok(Some(data.as_ref().clone())); } @@ -206,7 +201,6 @@ macro_rules! get_idl { $self.idl_cache.insert(ncache_key, Box::new(idl.clone())) } Ok(db_r) - }) }}; } @@ -215,24 +209,22 @@ macro_rules! name2uuid { $self:expr, $name:expr ) => {{ - spanned!("be::idl_arc_sqlite::name2uuid", { - let cache_key = NameCacheKey::Name2Uuid($name.to_string()); - let cache_r = $self.name_cache.get(&cache_key); - if let Some(NameCacheValue::U(uuid)) = cache_r { - trace!(?uuid, "Got cached name2uuid"); - return Ok(Some(uuid.clone())); - } else { - trace!("Cache miss uuid for name2uuid"); - } + let cache_key = NameCacheKey::Name2Uuid($name.to_string()); + let cache_r = $self.name_cache.get(&cache_key); + if let Some(NameCacheValue::U(uuid)) = cache_r { + trace!(?uuid, "Got cached name2uuid"); + return Ok(Some(uuid.clone())); + } else { + trace!("Cache miss uuid for name2uuid"); + } - let db_r = $self.db.name2uuid($name)?; - if let Some(uuid) = db_r { - $self - .name_cache - .insert(cache_key, NameCacheValue::U(uuid.clone())) - } - Ok(db_r) - }) + let db_r = $self.db.name2uuid($name)?; + if let Some(uuid) = db_r { + $self + .name_cache + .insert(cache_key, NameCacheValue::U(uuid.clone())) + } + Ok(db_r) }}; } @@ -241,24 +233,22 @@ macro_rules! uuid2spn { $self:expr, $uuid:expr ) => {{ - spanned!("be::idl_arc_sqlite::uuid2spn", { - let cache_key = NameCacheKey::Uuid2Spn($uuid); - let cache_r = $self.name_cache.get(&cache_key); - if let Some(NameCacheValue::S(ref spn)) = cache_r { - trace!(?spn, "Got cached uuid2spn"); - return Ok(Some(spn.as_ref().clone())); - } else { - trace!("Cache miss spn for uuid2spn"); - } + let cache_key = NameCacheKey::Uuid2Spn($uuid); + let cache_r = $self.name_cache.get(&cache_key); + if let Some(NameCacheValue::S(ref spn)) = cache_r { + trace!(?spn, "Got cached uuid2spn"); + return Ok(Some(spn.as_ref().clone())); + } else { + trace!("Cache miss spn for uuid2spn"); + } - let db_r = $self.db.uuid2spn($uuid)?; - if let Some(ref data) = db_r { - $self - .name_cache - .insert(cache_key, NameCacheValue::S(Box::new(data.clone()))) - } - Ok(db_r) - }) + let db_r = $self.db.uuid2spn($uuid)?; + if let Some(ref data) = db_r { + $self + .name_cache + .insert(cache_key, NameCacheValue::S(Box::new(data.clone()))) + } + Ok(db_r) }}; } @@ -267,23 +257,21 @@ macro_rules! uuid2rdn { $self:expr, $uuid:expr ) => {{ - spanned!("be::idl_arc_sqlite::uuid2rdn", { - let cache_key = NameCacheKey::Uuid2Rdn($uuid); - let cache_r = $self.name_cache.get(&cache_key); - if let Some(NameCacheValue::R(ref rdn)) = cache_r { - return Ok(Some(rdn.clone())); - } else { - trace!("Cache miss rdn for uuid2rdn"); - } + let cache_key = NameCacheKey::Uuid2Rdn($uuid); + let cache_r = $self.name_cache.get(&cache_key); + if let Some(NameCacheValue::R(ref rdn)) = cache_r { + return Ok(Some(rdn.clone())); + } else { + trace!("Cache miss rdn for uuid2rdn"); + } - let db_r = $self.db.uuid2rdn($uuid)?; - if let Some(ref data) = db_r { - $self - .name_cache - .insert(cache_key, NameCacheValue::R(data.clone())) - } - Ok(db_r) - }) + let db_r = $self.db.uuid2rdn($uuid)?; + if let Some(ref data) = db_r { + $self + .name_cache + .insert(cache_key, NameCacheValue::R(data.clone())) + } + Ok(db_r) }}; } @@ -528,88 +516,83 @@ impl<'a> IdlArcSqliteTransaction for IdlArcSqliteWriteTransaction<'a> { } impl<'a> IdlArcSqliteWriteTransaction<'a> { + #[instrument(level = "debug", name = "idl_arc_sqlite::commit", skip_all)] pub fn commit(self) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::commit", { - let IdlArcSqliteWriteTransaction { - db, - mut entry_cache, - mut idl_cache, - mut name_cache, - op_ts_max, - allids, - maxid, - } = self; + let IdlArcSqliteWriteTransaction { + db, + mut entry_cache, + mut idl_cache, + mut name_cache, + op_ts_max, + allids, + maxid, + } = self; - // Write any dirty items to the disk. - spanned!("be::idl_arc_sqlite::commit", { - entry_cache - .iter_mut_mark_clean() - .try_for_each(|(k, v)| match v { - Some(e) => db.write_identry(e), - None => db.delete_identry(*k), - }) + // Write any dirty items to the disk. + entry_cache + .iter_mut_mark_clean() + .try_for_each(|(k, v)| match v { + Some(e) => db.write_identry(e), + None => db.delete_identry(*k), }) .map_err(|e| { admin_error!(?e, "Failed to sync entry cache to sqlite"); e })?; - spanned!("be::idl_arc_sqlite::commit", { - idl_cache.iter_mut_mark_clean().try_for_each(|(k, v)| { - match v { - Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl), - #[allow(clippy::unreachable)] - None => { - // Due to how we remove items, we always write an empty idl - // to the cache, so this should never be none. - // - // If it is none, this means we have memory corruption so we MUST - // panic. - // Why is `v` the `Option` type then? - unreachable!(); - } + idl_cache + .iter_mut_mark_clean() + .try_for_each(|(k, v)| { + match v { + Some(idl) => db.write_idl(k.a.as_str(), k.i, k.k.as_str(), idl), + #[allow(clippy::unreachable)] + None => { + // Due to how we remove items, we always write an empty idl + // to the cache, so this should never be none. + // + // If it is none, this means we have memory corruption so we MUST + // panic. + // Why is `v` the `Option` type then? + unreachable!(); } - }) + } }) .map_err(|e| { admin_error!(?e, "Failed to sync idl cache to sqlite"); e })?; - spanned!("be::idl_arc_sqlite::commit", { - name_cache - .iter_mut_mark_clean() - .try_for_each(|(k, v)| match (k, v) { - (NameCacheKey::Name2Uuid(k), Some(NameCacheValue::U(v))) => { - db.write_name2uuid_add(k, *v) - } - (NameCacheKey::Name2Uuid(k), None) => db.write_name2uuid_rem(k), - (NameCacheKey::Uuid2Spn(uuid), Some(NameCacheValue::S(v))) => { - db.write_uuid2spn(*uuid, Some(v)) - } - (NameCacheKey::Uuid2Spn(uuid), None) => db.write_uuid2spn(*uuid, None), - (NameCacheKey::Uuid2Rdn(uuid), Some(NameCacheValue::R(v))) => { - db.write_uuid2rdn(*uuid, Some(v)) - } - (NameCacheKey::Uuid2Rdn(uuid), None) => db.write_uuid2rdn(*uuid, None), + name_cache + .iter_mut_mark_clean() + .try_for_each(|(k, v)| match (k, v) { + (NameCacheKey::Name2Uuid(k), Some(NameCacheValue::U(v))) => { + db.write_name2uuid_add(k, *v) + } + (NameCacheKey::Name2Uuid(k), None) => db.write_name2uuid_rem(k), + (NameCacheKey::Uuid2Spn(uuid), Some(NameCacheValue::S(v))) => { + db.write_uuid2spn(*uuid, Some(v)) + } + (NameCacheKey::Uuid2Spn(uuid), None) => db.write_uuid2spn(*uuid, None), + (NameCacheKey::Uuid2Rdn(uuid), Some(NameCacheValue::R(v))) => { + db.write_uuid2rdn(*uuid, Some(v)) + } + (NameCacheKey::Uuid2Rdn(uuid), None) => db.write_uuid2rdn(*uuid, None), - _ => Err(OperationError::InvalidCacheState), - }) + _ => Err(OperationError::InvalidCacheState), }) .map_err(|e| { admin_error!(?e, "Failed to sync name cache to sqlite"); e })?; - // Undo the caches in the reverse order. - db.commit().map(|()| { - op_ts_max.commit(); - name_cache.commit(); - idl_cache.commit(); - entry_cache.commit(); - allids.commit(); - maxid.commit(); - }) + // Undo the caches in the reverse order. + db.commit().map(|()| { + op_ts_max.commit(); + name_cache.commit(); + idl_cache.commit(); + entry_cache.commit(); + allids.commit(); + maxid.commit(); }) } @@ -626,18 +609,16 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { where I: Iterator>, { - spanned!("be::idl_arc_sqlite::write_identries", { - entries.try_for_each(|e| { - trace!("Inserting {:?} to cache", e.get_id()); - if e.get_id() == 0 { - Err(OperationError::InvalidEntryId) - } else { - (*self.allids).insert_id(e.get_id()); - self.entry_cache - .insert_dirty(e.get_id(), Arc::new(e.clone())); - Ok(()) - } - }) + entries.try_for_each(|e| { + trace!("Inserting {:?} to cache", e.get_id()); + if e.get_id() == 0 { + Err(OperationError::InvalidEntryId) + } else { + (*self.allids).insert_id(e.get_id()); + self.entry_cache + .insert_dirty(e.get_id(), Arc::new(e.clone())); + Ok(()) + } }) } @@ -661,17 +642,15 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { where I: Iterator, { - spanned!("be::idl_arc_sqlite::delete_identry", { - idl.try_for_each(|i| { - trace!("Removing {:?} from cache", i); - if i == 0 { - Err(OperationError::InvalidEntryId) - } else { - (*self.allids).remove_id(i); - self.entry_cache.remove_dirty(i); - Ok(()) - } - }) + idl.try_for_each(|i| { + trace!("Removing {:?} from cache", i); + if i == 0 { + Err(OperationError::InvalidEntryId) + } else { + (*self.allids).remove_id(i); + self.entry_cache.remove_dirty(i); + Ok(()) + } }) } @@ -682,32 +661,30 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { idx_key: &str, idl: &IDLBitRange, ) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::write_idl", { - let cache_key = IdlCacheKey { - a: attr.into(), - i: itype, - k: idx_key.into(), - }; - // On idl == 0 the db will remove this, and synthesise an empty IdList on a miss - // but we can cache this as a new empty IdList instead, so that we can avoid the - // db lookup on this idl. - if idl.is_empty() { - self.idl_cache - .insert_dirty(cache_key, Box::new(IDLBitRange::new())); - } else { - self.idl_cache - .insert_dirty(cache_key, Box::new(idl.clone())); - } - // self.db.write_idl(audit, attr, itype, idx_key, idl) - Ok(()) - }) + let cache_key = IdlCacheKey { + a: attr.into(), + i: itype, + k: idx_key.into(), + }; + // On idl == 0 the db will remove this, and synthesise an empty IdList on a miss + // but we can cache this as a new empty IdList instead, so that we can avoid the + // db lookup on this idl. + if idl.is_empty() { + self.idl_cache + .insert_dirty(cache_key, Box::new(IDLBitRange::new())); + } else { + self.idl_cache + .insert_dirty(cache_key, Box::new(idl.clone())); + } + // self.db.write_idl(audit, attr, itype, idx_key, idl) + Ok(()) } pub fn optimise_dirty_idls(&mut self) { self.idl_cache.iter_mut_dirty().for_each(|(k, maybe_idl)| { if let Some(idl) = maybe_idl { if idl.maybe_compress() { - filter_trace!(?k, "Compressed idl"); + trace!(?k, "Compressed idl"); } } }) @@ -971,27 +948,21 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { uuid: Uuid, add: BTreeSet, ) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::write_name2uuid_add", { - add.into_iter().for_each(|k| { - let cache_key = NameCacheKey::Name2Uuid(k); - let cache_value = NameCacheValue::U(uuid); - self.name_cache.insert_dirty(cache_key, cache_value) - }); - Ok(()) - }) + add.into_iter().for_each(|k| { + let cache_key = NameCacheKey::Name2Uuid(k); + let cache_value = NameCacheValue::U(uuid); + self.name_cache.insert_dirty(cache_key, cache_value) + }); + Ok(()) } pub fn write_name2uuid_rem(&mut self, rem: BTreeSet) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::write_name2uuid_rem", { - // self.db.write_name2uuid_rem(audit, &rem).and_then(|_| { - rem.into_iter().for_each(|k| { - // why not just a for loop here... - let cache_key = NameCacheKey::Name2Uuid(k); - self.name_cache.remove_dirty(cache_key) - }); - Ok(()) - // }) - }) + rem.into_iter().for_each(|k| { + // why not just a for loop here... + let cache_key = NameCacheKey::Name2Uuid(k); + self.name_cache.remove_dirty(cache_key) + }); + Ok(()) } pub fn create_uuid2spn(&self) -> Result<(), OperationError> { @@ -999,16 +970,14 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { } pub fn write_uuid2spn(&mut self, uuid: Uuid, k: Option) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::write_uuid2spn", { - let cache_key = NameCacheKey::Uuid2Spn(uuid); - match k { - Some(v) => self - .name_cache - .insert_dirty(cache_key, NameCacheValue::S(Box::new(v))), - None => self.name_cache.remove_dirty(cache_key), - } - Ok(()) - }) + let cache_key = NameCacheKey::Uuid2Spn(uuid); + match k { + Some(v) => self + .name_cache + .insert_dirty(cache_key, NameCacheValue::S(Box::new(v))), + None => self.name_cache.remove_dirty(cache_key), + } + Ok(()) } pub fn create_uuid2rdn(&self) -> Result<(), OperationError> { @@ -1016,16 +985,14 @@ impl<'a> IdlArcSqliteWriteTransaction<'a> { } pub fn write_uuid2rdn(&mut self, uuid: Uuid, k: Option) -> Result<(), OperationError> { - spanned!("be::idl_arc_sqlite::write_uuid2rdn", { - let cache_key = NameCacheKey::Uuid2Rdn(uuid); - match k { - Some(s) => self - .name_cache - .insert_dirty(cache_key, NameCacheValue::R(s)), - None => self.name_cache.remove_dirty(cache_key), - } - Ok(()) - }) + let cache_key = NameCacheKey::Uuid2Rdn(uuid); + match k { + Some(s) => self + .name_cache + .insert_dirty(cache_key, NameCacheValue::R(s)), + None => self.name_cache.remove_dirty(cache_key), + } + Ok(()) } pub fn create_idx(&self, attr: &str, itype: IndexType) -> Result<(), OperationError> { diff --git a/kanidmd/idm/src/be/idl_sqlite.rs b/kanidmd/idm/src/be/idl_sqlite.rs index bc264cb5a..ecceb9f17 100644 --- a/kanidmd/idm/src/be/idl_sqlite.rs +++ b/kanidmd/idm/src/be/idl_sqlite.rs @@ -1,24 +1,22 @@ -use crate::be::dbentry::DbEntry; -use crate::be::dbentry::DbIdentSpn; -use crate::be::{BackendConfig, IdList, IdRawEntry, IdxKey, IdxSlope}; -use crate::entry::{Entry, EntryCommitted, EntrySealed}; -use crate::prelude::*; -use crate::value::{IndexType, Value}; +use std::convert::{TryFrom, TryInto}; +use std::sync::Arc; +use std::time::Duration; + // use crate::valueset; use hashbrown::HashMap; use idlset::v2::IDLBitRange; use kanidm_proto::v1::{ConsistencyError, OperationError}; use r2d2::Pool; use r2d2_sqlite::SqliteConnectionManager; -use rusqlite::Connection; -use rusqlite::OpenFlags; -use rusqlite::OptionalExtension; -use std::convert::{TryFrom, TryInto}; -use std::sync::Arc; -use std::time::Duration; -use tracing::trace; +use rusqlite::{Connection, OpenFlags, OptionalExtension}; use uuid::Uuid; +use crate::be::dbentry::{DbEntry, DbIdentSpn}; +use crate::be::{BackendConfig, IdList, IdRawEntry, IdxKey, IdxSlope}; +use crate::entry::{Entry, EntryCommitted, EntrySealed}; +use crate::prelude::*; +use crate::value::{IndexType, Value}; + // use uuid::Uuid; const DBV_ID2ENTRY: &str = "id2entry"; @@ -117,12 +115,10 @@ pub trait IdlSqliteTransaction { fn get_conn(&self) -> &r2d2::PooledConnection; fn get_identry(&self, idl: &IdList) -> Result>, OperationError> { - spanned!("be::idl_sqlite::get_identry", { - self.get_identry_raw(idl)? - .into_iter() - .map(|ide| ide.into_entry().map(Arc::new)) - .collect() - }) + self.get_identry_raw(idl)? + .into_iter() + .map(|ide| ide.into_entry().map(Arc::new)) + .collect() } fn get_identry_raw(&self, idl: &IdList) -> Result, OperationError> { @@ -220,112 +216,104 @@ pub trait IdlSqliteTransaction { itype: IndexType, idx_key: &str, ) -> Result, OperationError> { - spanned!("be::idl_sqlite::get_idl", { - if !(self.exists_idx(attr, itype)?) { - filter_error!( - "IdlSqliteTransaction: Index {:?} {:?} not found", - itype, - attr - ); - return Ok(None); - } - // The table exists - lets now get the actual index itself. - - let query = format!( - "SELECT idl FROM idx_{}_{} WHERE key = :idx_key", - itype.as_idx_str(), + if !(self.exists_idx(attr, itype)?) { + filter_error!( + "IdlSqliteTransaction: Index {:?} {:?} not found", + itype, attr ); - let mut stmt = self - .get_conn() - .prepare(query.as_str()) - .map_err(sqlite_error)?; - let idl_raw: Option> = stmt - .query_row(&[(":idx_key", &idx_key)], |row| row.get(0)) - // We don't mind if it doesn't exist - .optional() - .map_err(sqlite_error)?; + return Ok(None); + } + // The table exists - lets now get the actual index itself. - let idl = match idl_raw { - Some(d) => serde_json::from_slice(d.as_slice()).map_err(serde_json_error)?, - // We don't have this value, it must be empty (or we - // have a corrupted index ..... - None => IDLBitRange::new(), - }; - trace!(%idl, "Got idl for index {:?} {:?}", itype, attr); + let query = format!( + "SELECT idl FROM idx_{}_{} WHERE key = :idx_key", + itype.as_idx_str(), + attr + ); + let mut stmt = self + .get_conn() + .prepare(query.as_str()) + .map_err(sqlite_error)?; + let idl_raw: Option> = stmt + .query_row(&[(":idx_key", &idx_key)], |row| row.get(0)) + // We don't mind if it doesn't exist + .optional() + .map_err(sqlite_error)?; - Ok(Some(idl)) - }) + let idl = match idl_raw { + Some(d) => serde_json::from_slice(d.as_slice()).map_err(serde_json_error)?, + // We don't have this value, it must be empty (or we + // have a corrupted index ..... + None => IDLBitRange::new(), + }; + + trace!( + miss_index = ?itype, + attr = ?attr, + idl = %idl, + ); + + Ok(Some(idl)) } fn name2uuid(&mut self, name: &str) -> Result, OperationError> { - spanned!("be::idl_sqlite::name2uuid", { - // The table exists - lets now get the actual index itself. - let mut stmt = self - .get_conn() - .prepare("SELECT uuid FROM idx_name2uuid WHERE name = :name") - .map_err(sqlite_error)?; - let uuid_raw: Option = stmt - .query_row(&[(":name", &name)], |row| row.get(0)) - // We don't mind if it doesn't exist - .optional() - .map_err(sqlite_error)?; + // The table exists - lets now get the actual index itself. + let mut stmt = self + .get_conn() + .prepare("SELECT uuid FROM idx_name2uuid WHERE name = :name") + .map_err(sqlite_error)?; + let uuid_raw: Option = stmt + .query_row(&[(":name", &name)], |row| row.get(0)) + // We don't mind if it doesn't exist + .optional() + .map_err(sqlite_error)?; - let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok()); - trace!(%name, ?uuid, "Got uuid for index"); + let uuid = uuid_raw.as_ref().and_then(|u| Uuid::parse_str(u).ok()); - Ok(uuid) - }) + Ok(uuid) } fn uuid2spn(&mut self, uuid: Uuid) -> Result, OperationError> { - spanned!("be::idl_sqlite::uuid2spn", { - let uuids = uuid.as_hyphenated().to_string(); - // The table exists - lets now get the actual index itself. - let mut stmt = self - .get_conn() - .prepare("SELECT spn FROM idx_uuid2spn WHERE uuid = :uuid") - .map_err(sqlite_error)?; - let spn_raw: Option> = stmt - .query_row(&[(":uuid", &uuids)], |row| row.get(0)) - // We don't mind if it doesn't exist - .optional() - .map_err(sqlite_error)?; + let uuids = uuid.as_hyphenated().to_string(); + // The table exists - lets now get the actual index itself. + let mut stmt = self + .get_conn() + .prepare("SELECT spn FROM idx_uuid2spn WHERE uuid = :uuid") + .map_err(sqlite_error)?; + let spn_raw: Option> = stmt + .query_row(&[(":uuid", &uuids)], |row| row.get(0)) + // We don't mind if it doesn't exist + .optional() + .map_err(sqlite_error)?; - let spn: Option = match spn_raw { - Some(d) => { - let dbv: DbIdentSpn = - serde_json::from_slice(d.as_slice()).map_err(serde_json_error)?; + let spn: Option = match spn_raw { + Some(d) => { + let dbv: DbIdentSpn = + serde_json::from_slice(d.as_slice()).map_err(serde_json_error)?; - Some(Value::from(dbv)) - } - None => None, - }; + Some(Value::from(dbv)) + } + None => None, + }; - trace!(?uuid, ?spn, "Got spn for uuid"); - - Ok(spn) - }) + Ok(spn) } fn uuid2rdn(&mut self, uuid: Uuid) -> Result, OperationError> { - spanned!("be::idl_sqlite::uuid2rdn", { - let uuids = uuid.as_hyphenated().to_string(); - // The table exists - lets now get the actual index itself. - let mut stmt = self - .get_conn() - .prepare("SELECT rdn FROM idx_uuid2rdn WHERE uuid = :uuid") - .map_err(sqlite_error)?; - let rdn: Option = stmt - .query_row(&[(":uuid", &uuids)], |row| row.get(0)) - // We don't mind if it doesn't exist - .optional() - .map_err(sqlite_error)?; + let uuids = uuid.as_hyphenated().to_string(); + // The table exists - lets now get the actual index itself. + let mut stmt = self + .get_conn() + .prepare("SELECT rdn FROM idx_uuid2rdn WHERE uuid = :uuid") + .map_err(sqlite_error)?; + let rdn: Option = stmt + .query_row(&[(":uuid", &uuids)], |row| row.get(0)) + // We don't mind if it doesn't exist + .optional() + .map_err(sqlite_error)?; - trace!(?uuid, ?rdn, "Got rdn for uuid"); - - Ok(rdn) - }) + Ok(rdn) } fn get_db_s_uuid(&self) -> Result, OperationError> { @@ -422,8 +410,8 @@ pub trait IdlSqliteTransaction { }) } + #[instrument(level = "debug", name = "idl_sqlite::get_allids", skip_all)] fn get_allids(&self) -> Result { - trace!("Building allids..."); let mut stmt = self .get_conn() .prepare("SELECT id FROM id2entry") @@ -604,20 +592,18 @@ impl IdlSqliteWriteTransaction { } } + #[instrument(level = "debug", name = "idl_sqlite::commit", skip_all)] pub fn commit(mut self) -> Result<(), OperationError> { - spanned!("be::idl_sqlite::commit", { - trace!("Commiting BE WR txn"); - assert!(!self.committed); - self.committed = true; + assert!(!self.committed); + self.committed = true; - self.conn - .execute("COMMIT TRANSACTION", []) - .map(|_| ()) - .map_err(|e| { - admin_error!(?e, "CRITICAL: failed to commit sqlite txn"); - OperationError::BackendEngine - }) - }) + self.conn + .execute("COMMIT TRANSACTION", []) + .map(|_| ()) + .map_err(|e| { + admin_error!(?e, "CRITICAL: failed to commit sqlite txn"); + OperationError::BackendEngine + }) } pub fn get_id2entry_max_id(&self) -> Result { @@ -770,46 +756,42 @@ impl IdlSqliteWriteTransaction { idx_key: &str, idl: &IDLBitRange, ) -> Result<(), OperationError> { - spanned!("be::idl_sqlite::write_idl", { - if idl.is_empty() { - trace!(?idl, "purging idl"); - // delete it - // Delete this idx_key from the table. - let query = format!( - "DELETE FROM idx_{}_{} WHERE key = :key", - itype.as_idx_str(), - attr - ); + if idl.is_empty() { + // delete it + // Delete this idx_key from the table. + let query = format!( + "DELETE FROM idx_{}_{} WHERE key = :key", + itype.as_idx_str(), + attr + ); - self.conn - .prepare(query.as_str()) - .and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)])) - .map_err(sqlite_error) - } else { - trace!(?idl, "writing idl"); - // Serialise the IdList to Vec - let idl_raw = serde_json::to_vec(idl).map_err(serde_json_error)?; + self.conn + .prepare(query.as_str()) + .and_then(|mut stmt| stmt.execute(&[(":key", &idx_key)])) + .map_err(sqlite_error) + } else { + // Serialise the IdList to Vec + let idl_raw = serde_json::to_vec(idl).map_err(serde_json_error)?; - // update or create it. - let query = format!( - "INSERT OR REPLACE INTO idx_{}_{} (key, idl) VALUES(:key, :idl)", - itype.as_idx_str(), - attr - ); + // update or create it. + let query = format!( + "INSERT OR REPLACE INTO idx_{}_{} (key, idl) VALUES(:key, :idl)", + itype.as_idx_str(), + attr + ); - self.conn - .prepare(query.as_str()) - .and_then(|mut stmt| { - stmt.execute(named_params! { - ":key": &idx_key, - ":idl": &idl_raw - }) + self.conn + .prepare(query.as_str()) + .and_then(|mut stmt| { + stmt.execute(named_params! { + ":key": &idx_key, + ":idl": &idl_raw }) - .map_err(sqlite_error) - } - // Get rid of the sqlite rows usize - .map(|_| ()) - }) + }) + .map_err(sqlite_error) + } + // Get rid of the sqlite rows usize + .map(|_| ()) } pub fn create_name2uuid(&self) -> Result<(), OperationError> { @@ -944,7 +926,7 @@ impl IdlSqliteWriteTransaction { itype.as_idx_str(), attr ); - trace!(idx = %idx_stmt, "Creating index"); + trace!(idx = %idx_stmt, "creating index"); self.conn .execute(idx_stmt.as_str(), []) @@ -1034,7 +1016,6 @@ impl IdlSqliteWriteTransaction { } pub unsafe fn purge_id2entry(&self) -> Result<(), OperationError> { - trace!("purge id2entry ..."); self.conn .execute("DELETE FROM id2entry", []) .map(|_| ()) @@ -1175,7 +1156,6 @@ impl IdlSqliteWriteTransaction { // If the table is empty, populate the versions as 0. let mut dbv_id2entry = self.get_db_version_key(DBV_ID2ENTRY); - trace!(initial = %dbv_id2entry, "dbv_id2entry"); // Check db_version here. // * if 0 -> create v1. @@ -1374,13 +1354,12 @@ impl IdlSqlite { } pub(crate) fn get_allids_count(&self) -> Result { - trace!("Counting allids..."); #[allow(clippy::expect_used)] self.pool .try_get() .expect("Unable to get connection from pool!!!") .query_row("select count(id) from id2entry", [], |row| row.get(0)) - .map_err(sqlite_error) // this was initially `ltrace`, but I think that was a mistake so I replaced it anyways. + .map_err(sqlite_error) } pub fn read(&self) -> IdlSqliteReadTransaction { diff --git a/kanidmd/idm/src/be/idxkey.rs b/kanidmd/idm/src/be/idxkey.rs index b27603103..3cdb4a9f0 100644 --- a/kanidmd/idm/src/be/idxkey.rs +++ b/kanidmd/idm/src/be/idxkey.rs @@ -1,9 +1,11 @@ -use crate::value::IndexType; -use smartstring::alias::String as AttrString; use std::borrow::Borrow; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; +use smartstring::alias::String as AttrString; + +use crate::value::IndexType; + pub type IdxSlope = u8; // Huge props to https://github.com/sunshowers/borrow-complex-key-example/blob/master/src/lib.rs diff --git a/kanidmd/idm/src/be/mod.rs b/kanidmd/idm/src/be/mod.rs index 680e0d544..0059697b9 100644 --- a/kanidmd/idm/src/be/mod.rs +++ b/kanidmd/idm/src/be/mod.rs @@ -4,35 +4,32 @@ //! is to persist content safely to disk, load that content, and execute queries //! utilising indexes in the most effective way possible. -use std::fs; - -use crate::prelude::*; -use crate::value::IndexType; -use hashbrown::HashMap as Map; -use hashbrown::HashSet; use std::cell::UnsafeCell; +use std::fs; +use std::ops::DerefMut; use std::sync::Arc; +use std::time::Duration; + +use concread::cowcell::*; +use hashbrown::{HashMap as Map, HashSet}; +use idlset::v2::IDLBitRange; +use idlset::AndNot; +use kanidm_proto::v1::{ConsistencyError, OperationError}; +use smartstring::alias::String as AttrString; use tracing::{trace, trace_span}; +use uuid::Uuid; use crate::be::dbentry::{DbBackup, DbEntry}; use crate::entry::{Entry, EntryCommitted, EntryNew, EntrySealed}; use crate::filter::{Filter, FilterPlan, FilterResolved, FilterValidResolved}; use crate::identity::Limits; -use crate::value::Value; -use concread::cowcell::*; -use idlset::v2::IDLBitRange; -use idlset::AndNot; -use kanidm_proto::v1::{ConsistencyError, OperationError}; -use smartstring::alias::String as AttrString; -use std::ops::DerefMut; -use std::time::Duration; -use uuid::Uuid; - +use crate::prelude::*; use crate::repl::cid::Cid; use crate::repl::ruv::{ ReplicationUpdateVector, ReplicationUpdateVectorReadTransaction, ReplicationUpdateVectorTransaction, ReplicationUpdateVectorWriteTransaction, }; +use crate::value::{IndexType, Value}; pub mod dbentry; pub mod dbvalue; @@ -41,12 +38,10 @@ mod idl_sqlite; pub(crate) mod idxkey; pub(crate) use self::idxkey::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxSlope}; - use crate::be::idl_arc_sqlite::{ IdlArcSqlite, IdlArcSqliteReadTransaction, IdlArcSqliteTransaction, IdlArcSqliteWriteTransaction, }; - // Re-export this pub use crate::be::idl_sqlite::FsType; @@ -175,6 +170,7 @@ pub trait BackendTransaction { /// Recursively apply a filter, transforming into IdList's on the way. This builds a query /// execution log, so that it can be examined how an operation proceeded. #[allow(clippy::cognitive_complexity)] + #[instrument(level = "debug", name = "be::filter2idl", skip_all)] fn filter2idl( &self, filt: &FilterResolved, @@ -534,6 +530,7 @@ pub trait BackendTransaction { }) } + #[instrument(level = "debug", name = "be::search", skip_all)] fn search( &self, erl: &Limits, @@ -543,165 +540,150 @@ pub trait BackendTransaction { // Unlike DS, even if we don't get the index back, we can just pass // to the in-memory filter test and be done. - spanned!("be::search", { - filter_trace!(?filt, "filter optimized"); + debug!(filter_optimised = ?filt); - let (idl, fplan) = trace_span!("be::search -> filter2idl").in_scope(|| { - spanned!("be::search -> filter2idl", { - self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD) - }) - })?; + let (idl, fplan) = trace_span!("be::search -> filter2idl") + .in_scope(|| self.filter2idl(filt.to_inner(), FILTER_SEARCH_TEST_THRESHOLD))?; - filter_trace!(?fplan, "filter executed plan"); + debug!(filter_executed_plan = ?fplan); - match &idl { - IdList::AllIds => { - if !erl.unindexed_allow { - admin_error!( - "filter (search) is fully unindexed, and not allowed by resource limits" - ); - return Err(OperationError::ResourceLimit); - } + match &idl { + IdList::AllIds => { + if !erl.unindexed_allow { + admin_error!( + "filter (search) is fully unindexed, and not allowed by resource limits" + ); + return Err(OperationError::ResourceLimit); } - IdList::Partial(idl_br) => { - // if idl_br.len() > erl.search_max_filter_test { - if !idl_br.below_threshold(erl.search_max_filter_test) { - admin_error!("filter (search) is partial indexed and greater than search_max_filter_test allowed by resource limits"); - return Err(OperationError::ResourceLimit); - } - } - IdList::PartialThreshold(_) => { - // Since we opted for this, this is not the fault - // of the user and we should not penalise them by limiting on partial. - } - IdList::Indexed(idl_br) => { - // We know this is resolved here, so we can attempt the limit - // check. This has to fold the whole index, but you know, class=pres is - // indexed ... - // if idl_br.len() > erl.search_max_results { - if !idl_br.below_threshold(erl.search_max_results) { - admin_error!("filter (search) is indexed and greater than search_max_results allowed by resource limits"); - return Err(OperationError::ResourceLimit); - } - } - }; - - let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { - admin_error!(?e, "get_identry failed"); - e - })?; - - let entries_filtered = match idl { - IdList::AllIds => trace_span!("be::search").in_scope(|| { - spanned!("be::search", { - entries - .into_iter() - .filter(|e| e.entry_match_no_index(filt)) - .collect() - }) - }), - IdList::Partial(_) => { - trace_span!("be::search").in_scope(|| { - entries - .into_iter() - .filter(|e| e.entry_match_no_index(filt)) - .collect() - }) - } - IdList::PartialThreshold(_) => trace_span!("be::search") - .in_scope(|| { - spanned!("be::search", { - entries - .into_iter() - .filter(|e| e.entry_match_no_index(filt)) - .collect() - }) - }), - // Since the index fully resolved, we can shortcut the filter test step here! - IdList::Indexed(_) => { - filter_trace!("filter (search) was fully indexed 👏"); - entries - } - }; - - // If the idl was not indexed, apply the resource limit now. Avoid the needless match since the - // if statement is quick. - if entries_filtered.len() > erl.search_max_results { - admin_error!("filter (search) is resolved and greater than search_max_results allowed by resource limits"); - return Err(OperationError::ResourceLimit); } + IdList::Partial(idl_br) => { + // if idl_br.len() > erl.search_max_filter_test { + if !idl_br.below_threshold(erl.search_max_filter_test) { + admin_error!("filter (search) is partial indexed and greater than search_max_filter_test allowed by resource limits"); + return Err(OperationError::ResourceLimit); + } + } + IdList::PartialThreshold(_) => { + // Since we opted for this, this is not the fault + // of the user and we should not penalise them by limiting on partial. + } + IdList::Indexed(idl_br) => { + // We know this is resolved here, so we can attempt the limit + // check. This has to fold the whole index, but you know, class=pres is + // indexed ... + // if idl_br.len() > erl.search_max_results { + if !idl_br.below_threshold(erl.search_max_results) { + admin_error!("filter (search) is indexed and greater than search_max_results allowed by resource limits"); + return Err(OperationError::ResourceLimit); + } + } + }; - Ok(entries_filtered) - }) + let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { + admin_error!(?e, "get_identry failed"); + e + })?; + + let entries_filtered = match idl { + IdList::AllIds => trace_span!("be::search").in_scope(|| { + entries + .into_iter() + .filter(|e| e.entry_match_no_index(filt)) + .collect() + }), + IdList::Partial(_) => trace_span!("be::search").in_scope(|| { + entries + .into_iter() + .filter(|e| e.entry_match_no_index(filt)) + .collect() + }), + IdList::PartialThreshold(_) => trace_span!("be::search") + .in_scope(|| { + entries + .into_iter() + .filter(|e| e.entry_match_no_index(filt)) + .collect() + }), + // Since the index fully resolved, we can shortcut the filter test step here! + IdList::Indexed(_) => { + filter_trace!("filter (search) was fully indexed 👏"); + entries + } + }; + + // If the idl was not indexed, apply the resource limit now. Avoid the needless match since the + // if statement is quick. + if entries_filtered.len() > erl.search_max_results { + admin_error!("filter (search) is resolved and greater than search_max_results allowed by resource limits"); + return Err(OperationError::ResourceLimit); + } + + Ok(entries_filtered) } /// Given a filter, assert some condition exists. /// Basically, this is a specialised case of search, where we don't need to /// load any candidates if they match. This is heavily used in uuid /// refint and attr uniqueness. + #[instrument(level = "debug", name = "be::exists", skip_all)] fn exists( &self, erl: &Limits, filt: &Filter, ) -> Result { - let _entered = trace_span!("be::exists").entered(); - spanned!("be::exists", { - filter_trace!(?filt, "filter optimised"); + debug!(filter_optimised = ?filt); - // Using the indexes, resolve the IdList here, or AllIds. - // Also get if the filter was 100% resolved or not. - let (idl, fplan) = spanned!("be::exists -> filter2idl", { - spanned!("be::exists -> filter2idl", { - self.filter2idl(filt.to_inner(), FILTER_EXISTS_TEST_THRESHOLD) - }) - })?; + // Using the indexes, resolve the IdList here, or AllIds. + // Also get if the filter was 100% resolved or not. + let (idl, fplan) = self.filter2idl(filt.to_inner(), FILTER_EXISTS_TEST_THRESHOLD)?; - filter_trace!(?fplan, "filter executed plan"); + debug!(filter_executed_plan = ?fplan); - // Apply limits to the IdList. - match &idl { - IdList::AllIds => { - if !erl.unindexed_allow { - admin_error!("filter (exists) is fully unindexed, and not allowed by resource limits"); - return Err(OperationError::ResourceLimit); - } + // Apply limits to the IdList. + match &idl { + IdList::AllIds => { + if !erl.unindexed_allow { + admin_error!( + "filter (exists) is fully unindexed, and not allowed by resource limits" + ); + return Err(OperationError::ResourceLimit); } - IdList::Partial(idl_br) => { - if !idl_br.below_threshold(erl.search_max_filter_test) { - admin_error!("filter (exists) is partial indexed and greater than search_max_filter_test allowed by resource limits"); - return Err(OperationError::ResourceLimit); - } - } - IdList::PartialThreshold(_) => { - // Since we opted for this, this is not the fault - // of the user and we should not penalise them. - } - IdList::Indexed(_) => {} } - - // Now, check the idl -- if it's fully resolved, we can skip this because the query - // was fully indexed. - match &idl { - IdList::Indexed(idl) => Ok(!idl.is_empty()), - _ => { - let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { - admin_error!(?e, "get_identry failed"); - e - })?; - - // if not 100% resolved query, apply the filter test. - let entries_filtered: Vec<_> = - spanned!("be::exists -> entry_match_no_index", { - entries - .into_iter() - .filter(|e| e.entry_match_no_index(filt)) - .collect() - }); - - Ok(!entries_filtered.is_empty()) + IdList::Partial(idl_br) => { + if !idl_br.below_threshold(erl.search_max_filter_test) { + admin_error!("filter (exists) is partial indexed and greater than search_max_filter_test allowed by resource limits"); + return Err(OperationError::ResourceLimit); } - } // end match idl - }) // end spanned + } + IdList::PartialThreshold(_) => { + // Since we opted for this, this is not the fault + // of the user and we should not penalise them. + } + IdList::Indexed(_) => {} + } + + // Now, check the idl -- if it's fully resolved, we can skip this because the query + // was fully indexed. + match &idl { + IdList::Indexed(idl) => Ok(!idl.is_empty()), + _ => { + let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { + admin_error!(?e, "get_identry failed"); + e + })?; + + // if not 100% resolved query, apply the filter test. + let entries_filtered: Vec<_> = + trace_span!("be::exists").in_scope(|| { + entries + .into_iter() + .filter(|e| e.entry_match_no_index(filt)) + .collect() + }); + + Ok(!entries_filtered.is_empty()) + } + } // end match idl } fn verify(&self) -> Vec> { @@ -878,6 +860,7 @@ pub trait BackendTransaction { impl<'a> BackendTransaction for BackendReadTransaction<'a> { type IdlLayerType = IdlArcSqliteReadTransaction<'a>; + type RuvType = ReplicationUpdateVectorReadTransaction<'a>; #[allow(clippy::mut_from_ref)] fn get_idlayer(&self) -> &mut IdlArcSqliteReadTransaction<'a> { @@ -895,8 +878,6 @@ impl<'a> BackendTransaction for BackendReadTransaction<'a> { unsafe { &mut (*self.idlayer.get()) } } - type RuvType = ReplicationUpdateVectorReadTransaction<'a>; - #[allow(clippy::mut_from_ref)] fn get_ruv(&self) -> &mut ReplicationUpdateVectorReadTransaction<'a> { unsafe { &mut (*self.ruv.get()) } @@ -930,14 +911,13 @@ impl<'a> BackendReadTransaction<'a> { impl<'a> BackendTransaction for BackendWriteTransaction<'a> { type IdlLayerType = IdlArcSqliteWriteTransaction<'a>; + type RuvType = ReplicationUpdateVectorWriteTransaction<'a>; #[allow(clippy::mut_from_ref)] fn get_idlayer(&self) -> &mut IdlArcSqliteWriteTransaction<'a> { unsafe { &mut (*self.idlayer.get()) } } - type RuvType = ReplicationUpdateVectorWriteTransaction<'a>; - #[allow(clippy::mut_from_ref)] fn get_ruv(&self) -> &mut ReplicationUpdateVectorWriteTransaction<'a> { unsafe { &mut (*self.ruv.get()) } @@ -949,181 +929,179 @@ impl<'a> BackendTransaction for BackendWriteTransaction<'a> { } impl<'a> BackendWriteTransaction<'a> { + #[instrument(level = "debug", name = "be::create", skip_all)] pub fn create( &self, cid: &Cid, entries: Vec>, ) -> Result>, OperationError> { - spanned!("be::create", { - if entries.is_empty() { - admin_error!("No entries provided to BE to create, invalid server call!"); - return Err(OperationError::EmptyRequest); + if entries.is_empty() { + admin_error!("No entries provided to BE to create, invalid server call!"); + return Err(OperationError::EmptyRequest); + } + + // Check that every entry has a change associated + // that matches the cid? + entries.iter().try_for_each(|e| { + if e.get_changelog().contains_tail_cid(cid) { + Ok(()) + } else { + admin_error!( + "Entry changelog does not contain a change related to this transaction" + ); + Err(OperationError::ReplEntryNotChanged) } + })?; - // Check that every entry has a change associated - // that matches the cid? - entries.iter().try_for_each(|e| { - if e.get_changelog().contains_tail_cid(cid) { - Ok(()) - } else { - admin_error!( - "Entry changelog does not contain a change related to this transaction" - ); - Err(OperationError::ReplEntryNotChanged) - } - })?; + let idlayer = self.get_idlayer(); + // Now, assign id's to all the new entries. - let idlayer = self.get_idlayer(); - // Now, assign id's to all the new entries. + let mut id_max = idlayer.get_id2entry_max_id()?; + let c_entries: Vec<_> = entries + .into_iter() + .map(|e| { + id_max += 1; + e.into_sealed_committed_id(id_max) + }) + .collect(); - let mut id_max = idlayer.get_id2entry_max_id()?; - let c_entries: Vec<_> = entries - .into_iter() - .map(|e| { - id_max += 1; - e.into_sealed_committed_id(id_max) - }) - .collect(); + // All good, lets update the RUV. + // This auto compresses. + let ruv_idl = IDLBitRange::from_iter(c_entries.iter().map(|e| e.get_id())); - // All good, lets update the RUV. - // This auto compresses. - let ruv_idl = IDLBitRange::from_iter(c_entries.iter().map(|e| e.get_id())); + self.get_ruv().insert_change(cid, ruv_idl)?; - self.get_ruv().insert_change(cid, ruv_idl)?; + idlayer.write_identries(c_entries.iter())?; - idlayer.write_identries(c_entries.iter())?; + idlayer.set_id2entry_max_id(id_max); - idlayer.set_id2entry_max_id(id_max); + // Now update the indexes as required. + for e in c_entries.iter() { + self.entry_index(None, Some(e))? + } - // Now update the indexes as required. - for e in c_entries.iter() { - self.entry_index(None, Some(e))? - } - - Ok(c_entries) - }) + Ok(c_entries) } + #[instrument(level = "debug", name = "be::modify", skip_all)] pub fn modify( &self, cid: &Cid, pre_entries: &[Arc], post_entries: &[EntrySealedCommitted], ) -> Result<(), OperationError> { - spanned!("be::modify", { - if post_entries.is_empty() || pre_entries.is_empty() { - admin_error!("No entries provided to BE to modify, invalid server call!"); - return Err(OperationError::EmptyRequest); + if post_entries.is_empty() || pre_entries.is_empty() { + admin_error!("No entries provided to BE to modify, invalid server call!"); + return Err(OperationError::EmptyRequest); + } + + assert!(post_entries.len() == pre_entries.len()); + + post_entries.iter().try_for_each(|e| { + if e.get_changelog().contains_tail_cid(cid) { + Ok(()) + } else { + admin_error!( + "Entry changelog does not contain a change related to this transaction" + ); + Err(OperationError::ReplEntryNotChanged) } + })?; - assert!(post_entries.len() == pre_entries.len()); + // All good, lets update the RUV. + // This auto compresses. + let ruv_idl = IDLBitRange::from_iter(post_entries.iter().map(|e| e.get_id())); + self.get_ruv().insert_change(cid, ruv_idl)?; - post_entries.iter().try_for_each(|e| { - if e.get_changelog().contains_tail_cid(cid) { - Ok(()) - } else { - admin_error!( - "Entry changelog does not contain a change related to this transaction" - ); - Err(OperationError::ReplEntryNotChanged) - } - })?; + // Now, given the list of id's, update them + self.get_idlayer().write_identries(post_entries.iter())?; - // All good, lets update the RUV. - // This auto compresses. - let ruv_idl = IDLBitRange::from_iter(post_entries.iter().map(|e| e.get_id())); - self.get_ruv().insert_change(cid, ruv_idl)?; - - // Now, given the list of id's, update them - self.get_idlayer().write_identries(post_entries.iter())?; - - // Finally, we now reindex all the changed entries. We do this by iterating and zipping - // over the set, because we know the list is in the same order. - pre_entries - .iter() - .zip(post_entries.iter()) - .try_for_each(|(pre, post)| self.entry_index(Some(pre.as_ref()), Some(post))) - }) + // Finally, we now reindex all the changed entries. We do this by iterating and zipping + // over the set, because we know the list is in the same order. + pre_entries + .iter() + .zip(post_entries.iter()) + .try_for_each(|(pre, post)| self.entry_index(Some(pre.as_ref()), Some(post))) } + #[instrument(level = "debug", name = "be::reap_tombstones", skip_all)] pub fn reap_tombstones(&self, cid: &Cid) -> Result { - spanned!("be::reap_tombstones", { - // We plan to clear the RUV up to this cid. So we need to build an IDL - // of all the entries we need to examine. - let idl = self.get_ruv().trim_up_to(cid).map_err(|e| { - admin_error!(?e, "failed to trim RUV to {:?}", cid); + // We plan to clear the RUV up to this cid. So we need to build an IDL + // of all the entries we need to examine. + let idl = self.get_ruv().trim_up_to(cid).map_err(|e| { + admin_error!(?e, "failed to trim RUV to {:?}", cid); + e + })?; + + let entries = self + .get_idlayer() + .get_identry(&IdList::Indexed(idl)) + .map_err(|e| { + admin_error!(?e, "get_identry failed"); e })?; - let entries = self - .get_idlayer() - .get_identry(&IdList::Indexed(idl)) - .map_err(|e| { - admin_error!(?e, "get_identry failed"); - e - })?; + if entries.is_empty() { + admin_info!("No entries affected - reap_tombstones operation success"); + return Ok(0); + } - if entries.is_empty() { - admin_info!("No entries affected - reap_tombstones operation success"); - return Ok(0); - } + // Now that we have a list of entries we need to partition them into + // two sets. The entries that are tombstoned and ready to reap_tombstones, and + // the entries that need to have their change logs trimmed. - // Now that we have a list of entries we need to partition them into - // two sets. The entries that are tombstoned and ready to reap_tombstones, and - // the entries that need to have their change logs trimmed. + // First we trim changelogs. Go through each entry, and trim the CL, and write it back. + let mut entries: Vec<_> = entries.iter().map(|er| er.as_ref().clone()).collect(); - // First we trim changelogs. Go through each entry, and trim the CL, and write it back. - let mut entries: Vec<_> = entries.iter().map(|er| er.as_ref().clone()).collect(); + entries + .iter_mut() + .try_for_each(|e| e.get_changelog_mut().trim_up_to(cid))?; - entries - .iter_mut() - .try_for_each(|e| e.get_changelog_mut().trim_up_to(cid))?; + // Write down the cl trims + self.get_idlayer().write_identries(entries.iter())?; - // Write down the cl trims - self.get_idlayer().write_identries(entries.iter())?; + let (tombstones, leftover): (Vec<_>, Vec<_>) = entries + .into_iter() + .partition(|e| e.get_changelog().can_delete()); - let (tombstones, leftover): (Vec<_>, Vec<_>) = entries - .into_iter() - .partition(|e| e.get_changelog().can_delete()); + // Assert that anything leftover still either is *alive* OR is a tombstone + // and has entries in the RUV! + let ruv_idls = self.get_ruv().ruv_idls(); - // Assert that anything leftover still either is *alive* OR is a tombstone - // and has entries in the RUV! - let ruv_idls = self.get_ruv().ruv_idls(); + if !leftover + .iter() + .all(|e| e.get_changelog().is_live() || ruv_idls.contains(e.get_id())) + { + admin_error!("Left over entries may be orphaned due to missing RUV entries"); + return Err(OperationError::ReplInvalidRUVState); + } - if !leftover - .iter() - .all(|e| e.get_changelog().is_live() || ruv_idls.contains(e.get_id())) - { - admin_error!("Left over entries may be orphaned due to missing RUV entries"); - return Err(OperationError::ReplInvalidRUVState); - } + // Now setup to reap_tombstones the tombstones. Remember, in the post cleanup, it's could + // now have been trimmed to a point we can purge them! - // Now setup to reap_tombstones the tombstones. Remember, in the post cleanup, it's could - // now have been trimmed to a point we can purge them! + // Assert the id's exist on the entry. + let id_list: IDLBitRange = tombstones.iter().map(|e| e.get_id()).collect(); - // Assert the id's exist on the entry. - let id_list: IDLBitRange = tombstones.iter().map(|e| e.get_id()).collect(); + // Ensure nothing here exists in the RUV index, else it means + // we didn't trim properly, or some other state violation has occured. + if !((&ruv_idls & &id_list).is_empty()) { + admin_error!("RUV still contains entries that are going to be removed."); + return Err(OperationError::ReplInvalidRUVState); + } - // Ensure nothing here exists in the RUV index, else it means - // we didn't trim properly, or some other state violation has occured. - if !((&ruv_idls & &id_list).is_empty()) { - admin_error!("RUV still contains entries that are going to be removed."); - return Err(OperationError::ReplInvalidRUVState); - } + // Now, given the list of id's, reap_tombstones them. + let sz = id_list.len(); + self.get_idlayer().delete_identry(id_list.into_iter())?; - // Now, given the list of id's, reap_tombstones them. - let sz = id_list.len(); - self.get_idlayer().delete_identry(id_list.into_iter())?; + // Finally, purge the indexes from the entries we removed. + tombstones + .iter() + .try_for_each(|e| self.entry_index(Some(e), None))?; - // Finally, purge the indexes from the entries we removed. - tombstones - .iter() - .try_for_each(|e| self.entry_index(Some(e), None))?; - - Ok(sz) - }) + Ok(sz) } + #[instrument(level = "debug", name = "be::update_idxmeta", skip_all)] pub fn update_idxmeta(&mut self, idxkeys: Vec) -> Result<(), OperationError> { if self.is_idx_slopeyness_generated()? { trace!("Indexing slopes available"); @@ -1522,25 +1500,24 @@ impl<'a> BackendWriteTransaction<'a> { } } + #[instrument(level = "debug", name = "be::ruv_rebuild", skip_all)] pub fn ruv_rebuild(&mut self) -> Result<(), OperationError> { // Rebuild the ruv! - spanned!("server::ruv_rebuild", { - // For now this has to read from all the entries in the DB, but in the future - // we'll actually store this properly (?). If it turns out this is really fast - // we may just rebuild this always on startup. + // For now this has to read from all the entries in the DB, but in the future + // we'll actually store this properly (?). If it turns out this is really fast + // we may just rebuild this always on startup. - // NOTE: An important detail is that we don't rely on indexes here! + // NOTE: An important detail is that we don't rely on indexes here! - let idl = IdList::AllIds; - let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { - admin_error!(?e, "get_identry failed"); - e - })?; + let idl = IdList::AllIds; + let entries = self.get_idlayer().get_identry(&idl).map_err(|e| { + admin_error!(?e, "get_identry failed"); + e + })?; - self.get_ruv().rebuild(&entries)?; + self.get_ruv().rebuild(&entries)?; - Ok(()) - }) + Ok(()) } pub fn commit(self) -> Result<(), OperationError> { @@ -1639,6 +1616,7 @@ fn get_idx_slope_default(ikey: &IdxKey) -> IdxSlope { // In the future this will do the routing between the chosen backends etc. impl Backend { + #[instrument(level = "debug", name = "be::new", skip_all)] pub fn new( mut cfg: BackendConfig, // path: &str, @@ -1675,40 +1653,38 @@ impl Backend { let ruv = Arc::new(ReplicationUpdateVector::default()); // this has a ::memory() type, but will path == "" work? - spanned!("be::new", { - let idlayer = Arc::new(IdlArcSqlite::new(&cfg, vacuum)?); - let be = Backend { - cfg, - idlayer, - ruv, - idxmeta: Arc::new(CowCell::new(IdxMeta::new(idxkeys))), - }; + let idlayer = Arc::new(IdlArcSqlite::new(&cfg, vacuum)?); + let be = Backend { + cfg, + idlayer, + ruv, + idxmeta: Arc::new(CowCell::new(IdxMeta::new(idxkeys))), + }; - // Now complete our setup with a txn - // In this case we can use an empty idx meta because we don't - // access any parts of - // the indexing subsystem here. - let mut idl_write = be.idlayer.write(); - idl_write - .setup() - .and_then(|_| idl_write.commit()) - .map_err(|e| { - admin_error!(?e, "Failed to setup idlayer"); - e - })?; + // Now complete our setup with a txn + // In this case we can use an empty idx meta because we don't + // access any parts of + // the indexing subsystem here. + let mut idl_write = be.idlayer.write(); + idl_write + .setup() + .and_then(|_| idl_write.commit()) + .map_err(|e| { + admin_error!(?e, "Failed to setup idlayer"); + e + })?; - // Now rebuild the ruv. - let mut be_write = be.write(); - be_write - .ruv_rebuild() - .and_then(|_| be_write.commit()) - .map_err(|e| { - admin_error!(?e, "Failed to reload ruv"); - e - })?; + // Now rebuild the ruv. + let mut be_write = be.write(); + be_write + .ruv_rebuild() + .and_then(|_| be_write.commit()) + .map_err(|e| { + admin_error!(?e, "Failed to reload ruv"); + e + })?; - Ok(be) - }) + Ok(be) } pub fn get_pool_size(&self) -> u32 { @@ -1762,22 +1738,23 @@ impl Backend { #[cfg(test)] mod tests { - use idlset::v2::IDLBitRange; use std::fs; use std::iter::FromIterator; use std::sync::Arc; + use std::time::Duration; + + use idlset::v2::IDLBitRange; use uuid::Uuid; use super::super::entry::{Entry, EntryInit, EntryNew}; use super::{ - Backend, BackendConfig, BackendTransaction, BackendWriteTransaction, IdList, OperationError, + Backend, BackendConfig, BackendTransaction, BackendWriteTransaction, DbBackup, IdList, + IdxKey, OperationError, }; - use super::{DbBackup, IdxKey}; use crate::identity::Limits; use crate::prelude::*; use crate::repl::cid::Cid; use crate::value::{IndexType, PartialValue, Value}; - use std::time::Duration; lazy_static! { static ref CID_ZERO: Cid = unsafe { Cid::new_zero() }; diff --git a/kanidmd/idm/src/config.rs b/kanidmd/idm/src/config.rs index c52035727..99c02e1d6 100644 --- a/kanidmd/idm/src/config.rs +++ b/kanidmd/idm/src/config.rs @@ -4,11 +4,12 @@ //! These components should be "per server". Any "per domain" config should be in the system //! or domain entries that are able to be replicated. +use std::fmt; +use std::str::FromStr; + use kanidm_proto::messages::ConsoleOutputMode; use rand::prelude::*; use serde::{Deserialize, Serialize}; -use std::fmt; -use std::str::FromStr; #[derive(Serialize, Deserialize, Debug)] pub struct IntegrationTestConfig { diff --git a/kanidmd/idm/src/credential/mod.rs b/kanidmd/idm/src/credential/mod.rs index 386feab81..b84d45425 100644 --- a/kanidmd/idm/src/credential/mod.rs +++ b/kanidmd/idm/src/credential/mod.rs @@ -1,20 +1,17 @@ -use crate::be::dbvalue::DbBackupCodeV1; -use crate::be::dbvalue::{DbCred, DbPasswordV1}; -use hashbrown::HashMap as Map; -use hashbrown::HashSet; +use std::convert::TryFrom; +use std::time::{Duration, Instant}; + +use hashbrown::{HashMap as Map, HashSet}; use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError}; use openssl::hash::MessageDigest; use openssl::pkcs5::pbkdf2_hmac; use openssl::sha::Sha512; use rand::prelude::*; -use std::convert::TryFrom; -use std::time::{Duration, Instant}; use uuid::Uuid; - -use webauthn_rs_core::proto::Credential as WebauthnCredential; -use webauthn_rs_core::proto::CredentialV3; - use webauthn_rs::prelude::{AuthenticationResult, Passkey, SecurityKey}; +use webauthn_rs_core::proto::{Credential as WebauthnCredential, CredentialV3}; + +use crate::be::dbvalue::{DbBackupCodeV1, DbCred, DbPasswordV1}; pub mod policy; pub mod softlock; @@ -234,12 +231,15 @@ impl BackupCodes { pub fn new(code_set: HashSet) -> Self { BackupCodes { code_set } } + pub fn verify(&self, code_chal: &str) -> bool { self.code_set.contains(code_chal) } + pub fn remove(&mut self, code_chal: &str) -> bool { self.code_set.remove(code_chal) } + pub fn to_dbbackupcodev1(&self) -> DbBackupCodeV1 { DbBackupCodeV1 { code_set: self.code_set.clone(), @@ -892,9 +892,10 @@ impl CredentialType { #[cfg(test)] mod tests { + use std::convert::TryFrom; + use crate::credential::policy::CryptoPolicy; use crate::credential::*; - use std::convert::TryFrom; #[test] fn test_credential_simple() { diff --git a/kanidmd/idm/src/credential/policy.rs b/kanidmd/idm/src/credential/policy.rs index 51bfa58fc..c0d34f00e 100644 --- a/kanidmd/idm/src/credential/policy.rs +++ b/kanidmd/idm/src/credential/policy.rs @@ -1,6 +1,7 @@ -use super::Password; use std::time::Duration; +use super::Password; + const PBKDF2_MIN_NIST_COST: u64 = 10000; #[derive(Debug)] diff --git a/kanidmd/idm/src/credential/totp.rs b/kanidmd/idm/src/credential/totp.rs index f25f02997..e42d2b50a 100644 --- a/kanidmd/idm/src/credential/totp.rs +++ b/kanidmd/idm/src/credential/totp.rs @@ -1,14 +1,13 @@ -use crate::be::dbvalue::{DbTotpAlgoV1, DbTotpV1}; +use std::convert::{TryFrom, TryInto}; +use std::time::{Duration, SystemTime}; + +use kanidm_proto::v1::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp}; use openssl::hash::MessageDigest; use openssl::pkey::PKey; use openssl::sign::Signer; use rand::prelude::*; -use std::convert::TryFrom; -use std::convert::TryInto; -use std::time::{Duration, SystemTime}; -use kanidm_proto::v1::TotpAlgo as ProtoTotpAlgo; -use kanidm_proto::v1::TotpSecret as ProtoTotp; +use crate::be::dbvalue::{DbTotpAlgoV1, DbTotpV1}; // This is 64 bits of entropy, as the examples in https://tools.ietf.org/html/rfc6238 show. const SECRET_SIZE_BYTES: usize = 8; @@ -192,9 +191,10 @@ impl Totp { #[cfg(test)] mod tests { - use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP}; use std::time::Duration; + use crate::credential::totp::{Totp, TotpAlgo, TotpError, TOTP_DEFAULT_STEP}; + #[test] fn hotp_basic() { let otp_sha1 = Totp::new(vec![0], 30, TotpAlgo::Sha1); diff --git a/kanidmd/idm/src/crypto.rs b/kanidmd/idm/src/crypto.rs index 419d472af..5bd96da7f 100644 --- a/kanidmd/idm/src/crypto.rs +++ b/kanidmd/idm/src/crypto.rs @@ -1,10 +1,11 @@ //! This module contains cryptographic setup code, a long with what policy //! and ciphers we accept. -use crate::config::Configuration; use openssl::error::ErrorStack; use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; +use crate::config::Configuration; + /// From the server configuration, generate an OpenSSL acceptor that we can use /// to build our sockets for https/ldaps. pub fn setup_tls(config: &Configuration) -> Result, ErrorStack> { diff --git a/kanidmd/idm/src/entry.rs b/kanidmd/idm/src/entry.rs index 2c326d036..d6a5243d2 100644 --- a/kanidmd/idm/src/entry.rs +++ b/kanidmd/idm/src/entry.rs @@ -24,6 +24,26 @@ //! [`filter`]: ../filter/index.html //! [`schema`]: ../schema/index.html +use std::cmp::Ordering; +pub use std::collections::BTreeSet as Set; +use std::collections::{BTreeMap as Map, BTreeMap, BTreeSet}; +use std::sync::Arc; + +use compact_jwt::JwsSigner; +use hashbrown::HashMap; +use kanidm_proto::v1::{ + ConsistencyError, Entry as ProtoEntry, Filter as ProtoFilter, OperationError, SchemaError, +}; +use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry}; +use smartstring::alias::String as AttrString; +use time::OffsetDateTime; +use tracing::trace; +use uuid::Uuid; +use webauthn_rs::prelude::{DeviceKey as DeviceKeyV4, Passkey as PasskeyV4}; + +use crate::be::dbentry::{DbEntry, DbEntryV2, DbEntryVers}; +use crate::be::dbvalue::DbValueSetV2; +use crate::be::{IdxKey, IdxSlope}; use crate::credential::Credential; use crate::filter::{Filter, FilterInvalid, FilterResolved, FilterValidResolved}; use crate::ldap::ldap_vattr_map; @@ -32,33 +52,8 @@ use crate::prelude::*; use crate::repl::cid::Cid; use crate::repl::entry::EntryChangelog; use crate::schema::{SchemaAttribute, SchemaClass, SchemaTransaction}; -use crate::value::{IndexType, SyntaxType}; -use crate::value::{IntentTokenState, PartialValue, Session, Value}; +use crate::value::{IndexType, IntentTokenState, PartialValue, Session, SyntaxType, Value}; use crate::valueset::{self, ValueSet}; -use kanidm_proto::v1::Entry as ProtoEntry; -use kanidm_proto::v1::Filter as ProtoFilter; -use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError}; -use tracing::trace; - -use crate::be::dbentry::{DbEntry, DbEntryV2, DbEntryVers}; -use crate::be::dbvalue::DbValueSetV2; -use crate::be::{IdxKey, IdxSlope}; - -use compact_jwt::JwsSigner; -use hashbrown::HashMap; -use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry}; -use smartstring::alias::String as AttrString; -use std::cmp::Ordering; -use std::collections::BTreeMap as Map; -pub use std::collections::BTreeSet as Set; -use std::collections::BTreeSet; -use std::sync::Arc; -use time::OffsetDateTime; -use uuid::Uuid; - -use std::collections::BTreeMap; -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; // use std::convert::TryFrom; // use std::str::FromStr; @@ -222,7 +217,6 @@ pub(crate) fn compare_attrs(left: &Eattrs, right: &Eattrs) -> bool { /// [`schema`]: ../schema/index.html /// [`access`]: ../access/index.html /// [`event`]: ../event/index.html -/// pub struct Entry { valid: VALID, state: STATE, @@ -323,29 +317,28 @@ impl Entry { /// Given a proto entry in JSON formed as a serialised string, processed that string /// into an Entry. + #[instrument(level = "debug", skip_all)] pub fn from_proto_entry_str( es: &str, qs: &QueryServerWriteTransaction, ) -> Result { - spanned!("from_proto_entry_str", { - if cfg!(test) { - if es.len() > 256 { - let (dsp_es, _) = es.split_at(255); - trace!("Parsing -> {}...", dsp_es); - } else { - trace!("Parsing -> {}", es); - } + if cfg!(test) { + if es.len() > 256 { + let (dsp_es, _) = es.split_at(255); + trace!("Parsing -> {}...", dsp_es); + } else { + trace!("Parsing -> {}", es); } - // str -> Proto entry - let pe: ProtoEntry = serde_json::from_str(es).map_err(|e| { - // We probably shouldn't print ES here because that would allow users - // to inject content into our logs :) - admin_error!(?e, "SerdeJson Failure"); - OperationError::SerdeJsonError - })?; - // now call from_proto_entry - Self::from_proto_entry(&pe, qs) - }) + } + // str -> Proto entry + let pe: ProtoEntry = serde_json::from_str(es).map_err(|e| { + // We probably shouldn't print ES here because that would allow users + // to inject content into our logs :) + admin_error!(?e, "SerdeJson Failure"); + OperationError::SerdeJsonError + })?; + // now call from_proto_entry + Self::from_proto_entry(&pe, qs) } #[cfg(test)] @@ -2471,13 +2464,15 @@ impl From<&SchemaClass> for Entry { #[cfg(test)] mod tests { + use std::collections::BTreeSet as Set; + + use hashbrown::HashMap; + use smartstring::alias::String as AttrString; + use crate::be::{IdxKey, IdxSlope}; use crate::entry::{Entry, EntryInit, EntryInvalid, EntryNew}; use crate::modify::{Modify, ModifyList}; use crate::value::{IndexType, PartialValue, Value}; - use hashbrown::HashMap; - use smartstring::alias::String as AttrString; - use std::collections::BTreeSet as Set; #[test] fn test_entry_basic() { diff --git a/kanidmd/idm/src/event.rs b/kanidmd/idm/src/event.rs index 3ad205d8d..c059e3618 100644 --- a/kanidmd/idm/src/event.rs +++ b/kanidmd/idm/src/event.rs @@ -15,6 +15,21 @@ //! with the operation, and a clear path to know how to transform events between //! various types. +use std::collections::BTreeSet; +#[cfg(test)] +use std::sync::Arc; +use std::time::Duration; + +use kanidm_proto::v1::{ + AuthCredential, AuthMech, AuthRequest, AuthStep, CreateRequest, DeleteRequest, + Entry as ProtoEntry, ModifyList as ProtoModifyList, ModifyRequest, OperationError, + SearchRequest, SearchResponse, WhoamiResponse, +}; +use ldap3_proto::simple::LdapFilter; +use uuid::Uuid; +#[cfg(test)] +use webauthn_rs::prelude::PublicKeyCredential; + use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced}; use crate::filter::{Filter, FilterInvalid, FilterValid}; use crate::identity::Limits; @@ -23,24 +38,6 @@ use crate::modify::{ModifyInvalid, ModifyList, ModifyValid}; use crate::prelude::*; use crate::schema::SchemaTransaction; use crate::value::PartialValue; -use kanidm_proto::v1::Entry as ProtoEntry; -use kanidm_proto::v1::ModifyList as ProtoModifyList; -use kanidm_proto::v1::OperationError; -use kanidm_proto::v1::{ - AuthCredential, AuthMech, AuthRequest, AuthStep, CreateRequest, DeleteRequest, ModifyRequest, - SearchRequest, SearchResponse, WhoamiResponse, -}; - -use ldap3_proto::simple::LdapFilter; -use std::collections::BTreeSet; -use std::time::Duration; -use uuid::Uuid; - -#[cfg(test)] -use std::sync::Arc; - -#[cfg(test)] -use webauthn_rs::prelude::PublicKeyCredential; #[derive(Debug)] pub struct SearchResult { diff --git a/kanidmd/idm/src/filter.rs b/kanidmd/idm/src/filter.rs index 85eafbd92..68b4d3961 100644 --- a/kanidmd/idm/src/filter.rs +++ b/kanidmd/idm/src/filter.rs @@ -8,28 +8,28 @@ //! [`Filter`]: struct.Filter.html //! [`Entry`]: ../entry/struct.Entry.html +use std::cmp::{Ordering, PartialOrd}; +use std::collections::BTreeSet; +use std::hash::Hash; +use std::iter; +use std::num::NonZeroU8; + +use concread::arcache::ARCacheReadTxn; +use hashbrown::HashMap; +#[cfg(test)] +use hashbrown::HashSet; +use kanidm_proto::v1::{Filter as ProtoFilter, OperationError, SchemaError}; +use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter}; +// use smartstring::alias::String as AttrString; +use serde::Deserialize; +use uuid::Uuid; + use crate::be::{IdxKey, IdxKeyRef, IdxKeyToRef, IdxMeta, IdxSlope}; use crate::identity::IdentityId; use crate::ldap::ldap_attr_filter_map; use crate::prelude::*; use crate::schema::SchemaTransaction; use crate::value::{IndexType, PartialValue}; -use concread::arcache::ARCacheReadTxn; -use kanidm_proto::v1::Filter as ProtoFilter; -use kanidm_proto::v1::{OperationError, SchemaError}; -use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter}; -// use smartstring::alias::String as AttrString; -use serde::Deserialize; -use std::cmp::{Ordering, PartialOrd}; -use std::collections::BTreeSet; -use std::hash::Hash; -use std::iter; -use std::num::NonZeroU8; -use uuid::Uuid; - -use hashbrown::HashMap; -#[cfg(test)] -use hashbrown::HashSet; const FILTER_DEPTH_MAX: usize = 16; @@ -491,51 +491,48 @@ impl Filter { // This has to have two versions to account for ro/rw traits, because RS can't // monomorphise on the trait to call clone_value. An option is to make a fn that // takes "clone_value(t, a, v) instead, but that may have a similar issue. + #[instrument(level = "debug", skip_all)] pub fn from_ro( ev: &Identity, f: &ProtoFilter, qs: &QueryServerReadTransaction, ) -> Result { - spanned!("filer::from_ro", { - let depth = FILTER_DEPTH_MAX; - let mut elems = ev.limits.filter_max_elements; - Ok(Filter { - state: FilterInvalid { - inner: FilterComp::from_ro(f, qs, depth, &mut elems)?, - }, - }) + let depth = FILTER_DEPTH_MAX; + let mut elems = ev.limits.filter_max_elements; + Ok(Filter { + state: FilterInvalid { + inner: FilterComp::from_ro(f, qs, depth, &mut elems)?, + }, }) } + #[instrument(level = "debug", skip_all)] pub fn from_rw( ev: &Identity, f: &ProtoFilter, qs: &QueryServerWriteTransaction, ) -> Result { - spanned!("filter::from_rw", { - let depth = FILTER_DEPTH_MAX; - let mut elems = ev.limits.filter_max_elements; - Ok(Filter { - state: FilterInvalid { - inner: FilterComp::from_rw(f, qs, depth, &mut elems)?, - }, - }) + let depth = FILTER_DEPTH_MAX; + let mut elems = ev.limits.filter_max_elements; + Ok(Filter { + state: FilterInvalid { + inner: FilterComp::from_rw(f, qs, depth, &mut elems)?, + }, }) } + #[instrument(level = "debug", skip_all)] pub fn from_ldap_ro( ev: &Identity, f: &LdapFilter, qs: &QueryServerReadTransaction, ) -> Result { - spanned!("filter::from_ldap_ro", { - let depth = FILTER_DEPTH_MAX; - let mut elems = ev.limits.filter_max_elements; - Ok(Filter { - state: FilterInvalid { - inner: FilterComp::from_ldap_ro(f, qs, depth, &mut elems)?, - }, - }) + let depth = FILTER_DEPTH_MAX; + let mut elems = ev.limits.filter_max_elements; + Ok(Filter { + state: FilterInvalid { + inner: FilterComp::from_ldap_ro(f, qs, depth, &mut elems)?, + }, }) } } @@ -948,7 +945,6 @@ impl PartialOrd for FilterResolved { impl Ord for FilterResolved { /// Ordering of filters for optimisation and subsequent dead term elimination. - /// fn cmp(&self, rhs: &FilterResolved) -> Ordering { let left_slopey = self.get_slopeyness_factor(); let right_slopey = rhs.get_slopeyness_factor(); @@ -1330,10 +1326,6 @@ impl FilterResolved { #[cfg(test)] mod tests { - use crate::event::CreateEvent; - use crate::event::DeleteEvent; - use crate::filter::{Filter, FilterInvalid, FILTER_DEPTH_MAX}; - use crate::prelude::*; use std::cmp::{Ordering, PartialOrd}; use std::collections::BTreeSet; use std::time::Duration; @@ -1341,6 +1333,10 @@ mod tests { use kanidm_proto::v1::Filter as ProtoFilter; use ldap3_proto::simple::LdapFilter; + use crate::event::{CreateEvent, DeleteEvent}; + use crate::filter::{Filter, FilterInvalid, FILTER_DEPTH_MAX}; + use crate::prelude::*; + #[test] fn test_filter_simple() { // Test construction. diff --git a/kanidmd/idm/src/identity.rs b/kanidmd/idm/src/identity.rs index 5fed6db8a..8d9098b97 100644 --- a/kanidmd/idm/src/identity.rs +++ b/kanidmd/idm/src/identity.rs @@ -3,12 +3,14 @@ //! and this provides the set of `Limits` to confine how many resources that the //! identity may consume during operations to prevent denial-of-service. -use crate::prelude::*; -use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; use std::hash::Hash; use std::sync::Arc; +use serde::{Deserialize, Serialize}; + +use crate::prelude::*; + #[derive(Debug, Clone)] /// Limits on the resources a single event can consume. These are defined per-event /// as they are derived from the userAuthToken based on that individual session diff --git a/kanidmd/idm/src/idm/account.rs b/kanidmd/idm/src/idm/account.rs index 0bc432354..d8084d85e 100644 --- a/kanidmd/idm/src/idm/account.rs +++ b/kanidmd/idm/src/idm/account.rs @@ -1,30 +1,27 @@ -use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed}; -use crate::prelude::*; -use crate::schema::SchemaTransaction; +use std::collections::{BTreeMap, BTreeSet}; +use std::time::Duration; -use kanidm_proto::v1::OperationError; -use kanidm_proto::v1::UiHint; -use kanidm_proto::v1::{AuthType, UserAuthToken}; -use kanidm_proto::v1::{BackupCodesView, CredentialStatus}; - -use webauthn_rs::prelude::CredentialID; -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; +use kanidm_proto::v1::{ + AuthType, BackupCodesView, CredentialStatus, OperationError, UiHint, UserAuthToken, +}; +use time::OffsetDateTime; +use uuid::Uuid; +use webauthn_rs::prelude::{ + AuthenticationResult, CredentialID, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, +}; use crate::constants::UUID_ANONYMOUS; use crate::credential::policy::CryptoPolicy; -use crate::credential::{softlock::CredSoftLockPolicy, Credential}; +use crate::credential::softlock::CredSoftLockPolicy; +use crate::credential::Credential; +use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed}; use crate::idm::group::Group; use crate::idm::server::IdmServerProxyWriteTransaction; use crate::modify::{ModifyInvalid, ModifyList}; +use crate::prelude::*; +use crate::schema::SchemaTransaction; use crate::value::{IntentTokenState, PartialValue, Value}; -use std::collections::{BTreeMap, BTreeSet}; -use std::time::Duration; -use time::OffsetDateTime; -use uuid::Uuid; -use webauthn_rs::prelude::AuthenticationResult; - lazy_static! { static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account"); static ref PVCLASS_POSIXACCOUNT: PartialValue = PartialValue::new_class("posixaccount"); @@ -153,34 +150,31 @@ pub(crate) struct Account { } impl Account { + #[instrument(level = "trace", skip_all)] pub(crate) fn try_from_entry_ro( value: &Entry, qs: &mut QueryServerReadTransaction, ) -> Result { - spanned!("idm::account::try_from_entry_ro", { - let groups = Group::try_from_account_entry_ro(value, qs)?; - try_from_entry!(value, groups) - }) + let groups = Group::try_from_account_entry_ro(value, qs)?; + try_from_entry!(value, groups) } + #[instrument(level = "trace", skip_all)] pub(crate) fn try_from_entry_rw( value: &Entry, qs: &mut QueryServerWriteTransaction, ) -> Result { - spanned!("idm::account::try_from_entry_rw", { - let groups = Group::try_from_account_entry_rw(value, qs)?; - try_from_entry!(value, groups) - }) + let groups = Group::try_from_account_entry_rw(value, qs)?; + try_from_entry!(value, groups) } + #[instrument(level = "trace", skip_all)] pub(crate) fn try_from_entry_reduced( value: &Entry, qs: &mut QueryServerReadTransaction, ) -> Result { - spanned!("idm::account::try_from_entry_reduced", { - let groups = Group::try_from_account_entry_red_ro(value, qs)?; - try_from_entry!(value, groups) - }) + let groups = Group::try_from_account_entry_red_ro(value, qs)?; + try_from_entry!(value, groups) } pub(crate) fn try_from_entry_no_groups( diff --git a/kanidmd/idm/src/idm/authsession.rs b/kanidmd/idm/src/idm/authsession.rs index 915449e12..1b05d63ce 100644 --- a/kanidmd/idm/src/idm/authsession.rs +++ b/kanidmd/idm/src/idm/authsession.rs @@ -2,34 +2,32 @@ //! Generally this has to process an authentication attempt, and validate each //! factor to assert that the user is legitimate. This also contains some //! support code for asynchronous task execution. -use crate::credential::BackupCodes; -use crate::idm::account::Account; -use crate::idm::delayed::BackupCodeRemoval; -use crate::idm::AuthState; -use crate::prelude::*; -use hashbrown::HashSet; -use kanidm_proto::v1::OperationError; -use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech, AuthType}; - -use crate::credential::{totp::Totp, Credential, CredentialType, Password}; - -use crate::idm::delayed::{DelayedAction, PasswordUpgrade, WebauthnCounterIncrement}; -// use crossbeam::channel::Sender; -use tokio::sync::mpsc::UnboundedSender as Sender; - -use std::time::Duration; -use uuid::Uuid; -// use webauthn_rs::proto::Credential as WebauthnCredential; -use compact_jwt::{Jws, JwsSigner}; use std::collections::BTreeMap; pub use std::collections::BTreeSet as Set; use std::convert::TryFrom; +use std::time::Duration; +// use webauthn_rs::proto::Credential as WebauthnCredential; +use compact_jwt::{Jws, JwsSigner}; +use hashbrown::HashSet; +use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech, AuthType, OperationError}; +// use crossbeam::channel::Sender; +use tokio::sync::mpsc::UnboundedSender as Sender; +use uuid::Uuid; +// use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; +use webauthn_rs::prelude::Passkey as PasskeyV4; use webauthn_rs::prelude::{ PasskeyAuthentication, RequestChallengeResponse, SecurityKeyAuthentication, Webauthn, }; -// use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; + +use crate::credential::totp::Totp; +use crate::credential::{BackupCodes, Credential, CredentialType, Password}; +use crate::idm::account::Account; +use crate::idm::delayed::{ + BackupCodeRemoval, DelayedAction, PasswordUpgrade, WebauthnCounterIncrement, +}; +use crate::idm::AuthState; +use crate::prelude::*; // Each CredHandler takes one or more credentials and determines if the // handlers requirements can be 100% fufilled. This is where MFA or other @@ -405,7 +403,9 @@ impl CredHandler { CredState::Denied(BAD_AUTH_TYPE_MSG) } } - } // end CredHandler::PasswordMfa + } + + // end CredHandler::PasswordMfa /// Validate a webauthn authentication attempt pub fn validate_webauthn( @@ -832,6 +832,16 @@ impl AuthSession { #[cfg(test)] mod tests { + pub use std::collections::BTreeSet as Set; + use std::time::Duration; + + use compact_jwt::JwsSigner; + use hashbrown::HashSet; + use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech}; + use tokio::sync::mpsc::unbounded_channel as unbounded; + use webauthn_authenticator_rs::softpasskey::SoftPasskey; + use webauthn_authenticator_rs::WebauthnAuthenticator; + use crate::credential::policy::CryptoPolicy; use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP}; use crate::credential::{BackupCodes, Credential}; @@ -842,17 +852,7 @@ mod tests { use crate::idm::delayed::DelayedAction; use crate::idm::AuthState; use crate::prelude::*; - use hashbrown::HashSet; - pub use std::collections::BTreeSet as Set; - use crate::utils::{duration_from_epoch_now, readable_password_from_random}; - use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthMech}; - use std::time::Duration; - - use tokio::sync::mpsc::unbounded_channel as unbounded; - use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator}; - - use compact_jwt::JwsSigner; fn create_pw_badlist_cache() -> HashSet { let mut s = HashSet::new(); diff --git a/kanidmd/idm/src/idm/credupdatesession.rs b/kanidmd/idm/src/idm/credupdatesession.rs index deac3e93c..63a789f48 100644 --- a/kanidmd/idm/src/idm/credupdatesession.rs +++ b/kanidmd/idm/src/idm/credupdatesession.rs @@ -1,36 +1,28 @@ -use crate::access::AccessControlsTransaction; -use crate::credential::{BackupCodes, Credential}; -use crate::idm::account::Account; -use crate::idm::server::IdmServerCredUpdateTransaction; -use crate::idm::server::IdmServerProxyWriteTransaction; -use crate::prelude::*; -use crate::value::IntentTokenState; -use hashbrown::HashSet; +use core::ops::Deref; use std::collections::BTreeMap; +use std::fmt; +use std::sync::{Arc, Mutex}; +use std::time::Duration; -use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP}; - +use hashbrown::HashSet; use kanidm_proto::v1::{ CURegState, CUStatus, CredentialDetail, PasskeyDetail, PasswordFeedback, TotpSecret, }; - -use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration}; - -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use webauthn_rs::prelude::{ - CreationChallengeResponse, PasskeyRegistration, RegisterPublicKeyCredential, + CreationChallengeResponse, DeviceKey as DeviceKeyV4, Passkey as PasskeyV4, PasskeyRegistration, + RegisterPublicKeyCredential, }; -use serde::{Deserialize, Serialize}; - -use std::fmt; -use std::sync::Arc; -use std::sync::Mutex; -use std::time::Duration; -use time::OffsetDateTime; - -use core::ops::Deref; +use crate::access::AccessControlsTransaction; +use crate::credential::totp::{Totp, TOTP_DEFAULT_STEP}; +use crate::credential::{BackupCodes, Credential}; +use crate::idm::account::Account; +use crate::idm::server::{IdmServerCredUpdateTransaction, IdmServerProxyWriteTransaction}; +use crate::prelude::*; +use crate::utils::{backup_code_from_random, readable_password_from_random, uuid_from_duration}; +use crate::value::IntentTokenState; const MAXIMUM_CRED_UPDATE_TTL: Duration = Duration::from_secs(900); const MAXIMUM_INTENT_TTL: Duration = Duration::from_secs(86400); @@ -155,7 +147,6 @@ pub struct CredentialUpdateSessionStatus { // The target user's display name displayname: String, // ttl: Duration, - // can_commit: bool, primary: Option, passkeys: Vec, @@ -384,85 +375,85 @@ impl<'a> IdmServerProxyWriteTransaction<'a> { Ok((CredentialUpdateSessionToken { token_enc }, status)) } + #[instrument(level = "debug", skip_all)] pub fn init_credential_update_intent( &mut self, event: &InitCredentialUpdateIntentEvent, ct: Duration, ) -> Result { - spanned!("idm::server::credupdatesession", { - let account = self.validate_init_credential_update(event.target, &event.ident)?; + let account = self.validate_init_credential_update(event.target, &event.ident)?; - // ==== AUTHORISATION CHECKED === + // ==== AUTHORISATION CHECKED === - // Build the intent token. - let mttl = event.max_ttl.unwrap_or_else(|| Duration::new(0, 0)); - let max_ttl = ct + mttl.clamp(MINIMUM_INTENT_TTL, MAXIMUM_INTENT_TTL); - // let sessionid = uuid_from_duration(max_ttl, self.sid); - let intent_id = readable_password_from_random(); + // Build the intent token. + let mttl = event.max_ttl.unwrap_or_else(|| Duration::new(0, 0)); + let max_ttl = ct + mttl.clamp(MINIMUM_INTENT_TTL, MAXIMUM_INTENT_TTL); + // let sessionid = uuid_from_duration(max_ttl, self.sid); + let intent_id = readable_password_from_random(); - /* - let token = CredentialUpdateIntentTokenInner { - sessionid, - target, - intent_id, - max_ttl, - }; + /* + let token = CredentialUpdateIntentTokenInner { + sessionid, + target, + intent_id, + max_ttl, + }; - let token_data = serde_json::to_vec(&token).map_err(|e| { - admin_error!(err = ?e, "Unable to encode token data"); - OperationError::SerdeJsonError + let token_data = serde_json::to_vec(&token).map_err(|e| { + admin_error!(err = ?e, "Unable to encode token data"); + OperationError::SerdeJsonError + })?; + + let token_enc = self + .token_enc_key + .encrypt_at_time(&token_data, ct.as_secs()); + */ + + // Mark that we have created an intent token on the user. + // ⚠️ -- remember, there is a risk, very low, but still a risk of collision of the intent_id. + // instead of enforcing unique, which would divulge that the collision occured, we + // write anyway, and instead on the intent access path we invalidate IF the collision + // occurs. + let mut modlist = ModifyList::new_append( + "credential_update_intent_token", + Value::IntentToken(intent_id.clone(), IntentTokenState::Valid { max_ttl }), + ); + + // Remove any old credential update intents + account + .credential_update_intent_tokens + .iter() + .for_each(|(existing_intent_id, state)| { + let max_ttl = match state { + IntentTokenState::Valid { max_ttl } + | IntentTokenState::InProgress { + max_ttl, + session_id: _, + session_ttl: _, + } + | IntentTokenState::Consumed { max_ttl } => *max_ttl, + }; + + if ct >= max_ttl { + modlist.push_mod(Modify::Removed( + AttrString::from("credential_update_intent_token"), + PartialValue::IntentToken(existing_intent_id.clone()), + )); + } + }); + + self.qs_write + .internal_modify( + // Filter as executed + &filter!(f_eq("uuid", PartialValue::new_uuid(account.uuid))), + &modlist, + ) + .map_err(|e| { + request_error!(error = ?e); + e })?; - let token_enc = self - .token_enc_key - .encrypt_at_time(&token_data, ct.as_secs()); - */ - - // Mark that we have created an intent token on the user. - // ⚠️ -- remember, there is a risk, very low, but still a risk of collision of the intent_id. - // instead of enforcing unique, which would divulge that the collision occured, we - // write anyway, and instead on the intent access path we invalidate IF the collision - // occurs. - let mut modlist = ModifyList::new_append( - "credential_update_intent_token", - Value::IntentToken(intent_id.clone(), IntentTokenState::Valid { max_ttl }), - ); - - // Remove any old credential update intents - account.credential_update_intent_tokens.iter().for_each( - |(existing_intent_id, state)| { - let max_ttl = match state { - IntentTokenState::Valid { max_ttl } - | IntentTokenState::InProgress { - max_ttl, - session_id: _, - session_ttl: _, - } - | IntentTokenState::Consumed { max_ttl } => *max_ttl, - }; - - if ct >= max_ttl { - modlist.push_mod(Modify::Removed( - AttrString::from("credential_update_intent_token"), - PartialValue::IntentToken(existing_intent_id.clone()), - )); - } - }, - ); - - self.qs_write - .internal_modify( - // Filter as executed - &filter!(f_eq("uuid", PartialValue::new_uuid(account.uuid))), - &modlist, - ) - .map_err(|e| { - request_error!(error = ?e); - e - })?; - - Ok(CredentialUpdateIntentToken { intent_id }) - }) + Ok(CredentialUpdateIntentToken { intent_id }) } pub fn exchange_intent_credential_update( @@ -642,21 +633,20 @@ impl<'a> IdmServerProxyWriteTransaction<'a> { self.create_credupdate_session(session_id, Some(intent_id), account, current_time) } + #[instrument(level = "debug", skip_all)] pub fn init_credential_update( &mut self, event: &InitCredentialUpdateEvent, ct: Duration, ) -> Result<(CredentialUpdateSessionToken, CredentialUpdateSessionStatus), OperationError> { - spanned!("idm::server::credupdatesession", { - let account = self.validate_init_credential_update(event.target, &event.ident)?; - // ==== AUTHORISATION CHECKED === - // This is the expiry time, so that our cleanup task can "purge up to now" rather - // than needing to do calculations. - let sessionid = uuid_from_duration(ct + MAXIMUM_CRED_UPDATE_TTL, self.sid); + let account = self.validate_init_credential_update(event.target, &event.ident)?; + // ==== AUTHORISATION CHECKED === + // This is the expiry time, so that our cleanup task can "purge up to now" rather + // than needing to do calculations. + let sessionid = uuid_from_duration(ct + MAXIMUM_CRED_UPDATE_TTL, self.sid); - // Build the cred update session. - self.create_credupdate_session(sessionid, None, account, ct) - }) + // Build the cred update session. + self.create_credupdate_session(sessionid, None, account, ct) } #[instrument(level = "trace", skip(self))] @@ -1472,6 +1462,14 @@ impl<'a> IdmServerCredUpdateTransaction<'a> { #[cfg(test)] mod tests { + use std::time::Duration; + + use async_std::task; + use kanidm_proto::v1::{AuthAllowed, AuthMech, CredentialDetailType}; + use uuid::uuid; + use webauthn_authenticator_rs::softpasskey::SoftPasskey; + use webauthn_authenticator_rs::WebauthnAuthenticator; + use super::{ CredentialUpdateSessionStatus, CredentialUpdateSessionToken, InitCredentialUpdateEvent, InitCredentialUpdateIntentEvent, MfaRegStateStatus, MAXIMUM_CRED_UPDATE_TTL, @@ -1481,16 +1479,8 @@ mod tests { use crate::event::{AuthEvent, AuthResult, CreateEvent}; use crate::idm::delayed::DelayedAction; use crate::idm::server::IdmServer; - use crate::prelude::*; - use std::time::Duration; - - use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator}; - use crate::idm::AuthState; - use kanidm_proto::v1::{AuthAllowed, AuthMech, CredentialDetailType}; - use uuid::uuid; - - use async_std::task; + use crate::prelude::*; const TEST_CURRENT_TIME: u64 = 6000; const TESTPERSON_UUID: Uuid = uuid!("cf231fea-1a8f-4410-a520-fd9b1a379c86"); diff --git a/kanidmd/idm/src/idm/event.rs b/kanidmd/idm/src/idm/event.rs index 082c1b234..523311d63 100644 --- a/kanidmd/idm/src/idm/event.rs +++ b/kanidmd/idm/src/idm/event.rs @@ -1,6 +1,7 @@ -use crate::prelude::*; use kanidm_proto::v1::OperationError; +use crate::prelude::*; + #[cfg(test)] pub(crate) struct PasswordChangeEvent { pub ident: Identity, diff --git a/kanidmd/idm/src/idm/group.rs b/kanidmd/idm/src/idm/group.rs index 86c324648..b90f33d2e 100644 --- a/kanidmd/idm/src/idm/group.rs +++ b/kanidmd/idm/src/idm/group.rs @@ -1,10 +1,9 @@ +use kanidm_proto::v1::{Group as ProtoGroup, OperationError}; +use uuid::Uuid; + use crate::entry::{Entry, EntryCommitted, EntryReduced, EntrySealed}; use crate::prelude::*; use crate::value::PartialValue; -use kanidm_proto::v1::Group as ProtoGroup; -use kanidm_proto::v1::OperationError; - -use uuid::Uuid; lazy_static! { static ref PVCLASS_GROUP: PartialValue = PartialValue::new_class("group"); diff --git a/kanidmd/idm/src/idm/mod.rs b/kanidmd/idm/src/idm/mod.rs index 36f4f52e9..76cb1ede8 100644 --- a/kanidmd/idm/src/idm/mod.rs +++ b/kanidmd/idm/src/idm/mod.rs @@ -15,10 +15,10 @@ pub mod server; pub(crate) mod serviceaccount; pub(crate) mod unix; -use kanidm_proto::v1::{AuthAllowed, AuthMech}; - use std::fmt; +use kanidm_proto::v1::{AuthAllowed, AuthMech}; + pub enum AuthState { Choose(Vec), Continue(Vec), diff --git a/kanidmd/idm/src/idm/oauth2.rs b/kanidmd/idm/src/idm/oauth2.rs index 84100d18a..7387902dc 100644 --- a/kanidmd/idm/src/idm/oauth2.rs +++ b/kanidmd/idm/src/idm/oauth2.rs @@ -3,30 +3,19 @@ //! This contains the in memory and loaded set of active oauth2 resource server //! integrations, which are then able to be used an accessed from the IDM layer //! for operations involving oauth2 authentication processing. -//! -use crate::identity::IdentityId; -use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant}; -use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction}; -use crate::prelude::*; -use crate::value::OAUTHSCOPE_RE; +use std::collections::{BTreeMap, BTreeSet}; +use std::convert::TryFrom; +use std::fmt; +use std::sync::Arc; +use std::time::Duration; + use base64urlsafedata::Base64UrlSafeData; pub use compact_jwt::{JwkKeySet, OidcToken}; use compact_jwt::{JwsSigner, OidcClaims, OidcSubject}; use concread::cowcell::*; use fernet::Fernet; use hashbrown::HashMap; -use kanidm_proto::v1::{AuthType, UserAuthToken}; -use openssl::sha; -use serde::{Deserialize, Serialize}; -use std::collections::{BTreeMap, BTreeSet}; -use std::fmt; -use std::sync::Arc; -use time::OffsetDateTime; -use tokio::sync::mpsc::UnboundedSender as Sender; -use tracing::trace; -use url::{Origin, Url}; - pub use kanidm_proto::oauth2::{ AccessTokenIntrospectRequest, AccessTokenIntrospectResponse, AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, CodeChallengeMethod, ErrorResponse, @@ -36,9 +25,19 @@ use kanidm_proto::oauth2::{ ClaimType, DisplayValue, GrantType, IdTokenSignAlg, ResponseMode, ResponseType, SubjectType, TokenEndpointAuthMethod, }; +use kanidm_proto::v1::{AuthType, UserAuthToken}; +use openssl::sha; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; +use tokio::sync::mpsc::UnboundedSender as Sender; +use tracing::trace; +use url::{Origin, Url}; -use std::convert::TryFrom; -use std::time::Duration; +use crate::identity::IdentityId; +use crate::idm::delayed::{DelayedAction, Oauth2ConsentGrant}; +use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerTransaction}; +use crate::prelude::*; +use crate::value::OAUTHSCOPE_RE; lazy_static! { static ref CLASS_OAUTH2: PartialValue = PartialValue::new_class("oauth2_resource_server"); @@ -1351,26 +1350,22 @@ fn parse_basic_authz(client_authz: &str) -> Result<(String, String), Oauth2Error #[cfg(test)] mod tests { - use crate::event::CreateEvent; + use std::convert::TryFrom; + use std::str::FromStr; + use std::time::Duration; + + use base64urlsafedata::Base64UrlSafeData; + use compact_jwt::{JwaAlg, Jwk, JwkUse, JwsValidator, OidcSubject, OidcUnverified}; + use kanidm_proto::oauth2::*; + use kanidm_proto::v1::{AuthType, UserAuthToken}; + use openssl::sha; + + use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::idm::delayed::DelayedAction; use crate::idm::oauth2::{AuthoriseResponse, Oauth2Error}; use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::prelude::*; - use crate::event::{DeleteEvent, ModifyEvent}; - - use base64urlsafedata::Base64UrlSafeData; - use kanidm_proto::oauth2::*; - use kanidm_proto::v1::{AuthType, UserAuthToken}; - - use compact_jwt::{JwaAlg, Jwk, JwkUse, JwsValidator, OidcSubject, OidcUnverified}; - - use openssl::sha; - - use std::convert::TryFrom; - use std::str::FromStr; - use std::time::Duration; - const TEST_CURRENT_TIME: u64 = 6000; const UAT_EXPIRE: u64 = 5; const TOKEN_EXPIRE: u64 = 900; diff --git a/kanidmd/idm/src/idm/radius.rs b/kanidmd/idm/src/idm/radius.rs index 9e064e3e0..6ea3eb794 100644 --- a/kanidmd/idm/src/idm/radius.rs +++ b/kanidmd/idm/src/idm/radius.rs @@ -1,14 +1,13 @@ -use crate::idm::group::Group; +use std::time::Duration; + +use kanidm_proto::v1::{OperationError, RadiusAuthToken}; +use time::OffsetDateTime; use uuid::Uuid; -use crate::prelude::*; - use crate::entry::{Entry, EntryCommitted, EntryReduced}; +use crate::idm::group::Group; +use crate::prelude::*; use crate::value::PartialValue; -use kanidm_proto::v1::OperationError; -use kanidm_proto::v1::RadiusAuthToken; -use std::time::Duration; -use time::OffsetDateTime; lazy_static! { static ref PVCLASS_ACCOUNT: PartialValue = PartialValue::new_class("account"); diff --git a/kanidmd/idm/src/idm/server.rs b/kanidmd/idm/src/idm/server.rs index 187189be1..c40bf598b 100644 --- a/kanidmd/idm/src/idm/server.rs +++ b/kanidmd/idm/src/idm/server.rs @@ -1,3 +1,35 @@ +use core::task::{Context, Poll}; +use std::convert::TryFrom; +use std::str::FromStr; +use std::sync::Arc; +use std::time::Duration; + +use async_std::task; +use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator}; +use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn}; +use concread::cowcell::{CowCellReadTxn, CowCellWriteTxn}; +use concread::hashmap::HashMap; +use concread::CowCell; +use fernet::Fernet; +// #[cfg(any(test,bench))] +use futures::task as futures_task; +use hashbrown::HashSet; +use kanidm_proto::v1::{ + ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UnixGroupToken, + UnixUserToken, UserAuthToken, +}; +use rand::prelude::*; +use tokio::sync::mpsc::{ + unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender, +}; +use tokio::sync::{Mutex, Semaphore}; +use tracing::trace; +use url::Url; +use webauthn_rs::prelude::{Webauthn, WebauthnBuilder}; + +use super::delayed::BackupCodeRemoval; +use super::event::ReadBackupCodeEvent; +use crate::actors::v1_write::QueryServerWriteV1; use crate::credential::policy::CryptoPolicy; use crate::credential::softlock::CredSoftLock; use crate::event::{AuthEvent, AuthEventStep, AuthResult}; @@ -5,6 +37,10 @@ use crate::identity::{IdentType, IdentUser, Limits}; use crate::idm::account::Account; use crate::idm::authsession::AuthSession; use crate::idm::credupdatesession::CredentialUpdateSessionMutex; +use crate::idm::delayed::{ + DelayedAction, Oauth2ConsentGrant, PasswordUpgrade, UnixPasswordUpgrade, + WebauthnCounterIncrement, +}; #[cfg(test)] use crate::idm::event::PasswordChangeEvent; use crate::idm::event::{ @@ -26,54 +62,6 @@ use crate::ldap::{LdapBoundToken, LdapSession}; use crate::prelude::*; use crate::utils::{password_from_random, readable_password_from_random, uuid_from_duration, Sid}; -use crate::actors::v1_write::QueryServerWriteV1; -use crate::idm::delayed::{ - DelayedAction, Oauth2ConsentGrant, PasswordUpgrade, UnixPasswordUpgrade, - WebauthnCounterIncrement, -}; - -use hashbrown::HashSet; -use kanidm_proto::v1::{ - ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UnixGroupToken, - UnixUserToken, UserAuthToken, -}; - -use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator}; -use fernet::Fernet; - -use tokio::sync::mpsc::{ - unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender, -}; -use tokio::sync::Semaphore; - -use async_std::task; - -// #[cfg(any(test,bench))] -use core::task::{Context, Poll}; -// #[cfg(any(test,bench))] -use futures::task as futures_task; - -use concread::{ - bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn}, - cowcell::{CowCellReadTxn, CowCellWriteTxn}, - hashmap::HashMap, - CowCell, -}; - -use rand::prelude::*; -use std::convert::TryFrom; -use std::str::FromStr; -use std::{sync::Arc, time::Duration}; -use tokio::sync::Mutex; -use url::Url; - -use webauthn_rs::prelude::{Webauthn, WebauthnBuilder}; - -use super::delayed::BackupCodeRemoval; -use super::event::ReadBackupCodeEvent; - -use tracing::trace; - type AuthSessionMutex = Arc>; type CredSoftLockMutex = Arc>; @@ -298,6 +286,7 @@ impl IdmServer { } /// Read from the database, in a transaction. + #[instrument(level = "debug", skip_all)] pub async fn proxy_read_async(&self) -> IdmServerProxyReadTransaction<'_> { IdmServerProxyReadTransaction { qs_read: self.qs.read_async().await, @@ -312,6 +301,7 @@ impl IdmServer { task::block_on(self.proxy_write_async(ts)) } + #[instrument(level = "debug", skip_all)] pub async fn proxy_write_async(&self, ts: Duration) -> IdmServerProxyWriteTransaction<'_> { let mut sid = [0; 4]; let mut rng = StdRng::from_entropy(); @@ -421,6 +411,7 @@ pub(crate) trait IdmServerTransaction<'a> { /// The primary method of verification selection is the use of the KID parameter /// that we internally sign with. We can use this to select the appropriate token type /// and validation method. + #[instrument(level = "info", skip_all)] fn validate_and_parse_token_to_ident( &self, token: Option<&str>, @@ -532,6 +523,7 @@ pub(crate) trait IdmServerTransaction<'a> { } } + #[instrument(level = "debug", skip_all)] fn validate_and_parse_uat( &self, token: Option<&str>, @@ -598,6 +590,7 @@ pub(crate) trait IdmServerTransaction<'a> { /// something we can pin access controls and other limits and references to. /// This is why it is the location where validity windows are checked and other /// relevant session information is injected. + #[instrument(level = "debug", skip_all)] fn process_uat_to_identity( &self, uat: &UserAuthToken, @@ -663,6 +656,7 @@ pub(crate) trait IdmServerTransaction<'a> { }) } + #[instrument(level = "debug", skip_all)] fn process_apit_to_identity( &self, apit: &ApiToken, @@ -683,6 +677,7 @@ pub(crate) trait IdmServerTransaction<'a> { }) } + #[instrument(level = "debug", skip_all)] fn validate_ldap_session( &self, session: &LdapSession, @@ -883,16 +878,14 @@ impl<'a> IdmServerAuthTransaction<'a> { match auth_session { Some(auth_session) => { let mut session_write = self.sessions.write(); - spanned!("idm::server::auth -> sessions", { - if session_write.contains_key(&sessionid) { - Err(OperationError::InvalidSessionState) - } else { - session_write.insert(sessionid, Arc::new(Mutex::new(auth_session))); - // Debugging: ensure we really inserted ... - debug_assert!(session_write.get(&sessionid).is_some()); - Ok(()) - } - })?; + if session_write.contains_key(&sessionid) { + Err(OperationError::InvalidSessionState) + } else { + session_write.insert(sessionid, Arc::new(Mutex::new(auth_session))); + // Debugging: ensure we really inserted ... + debug_assert!(session_write.get(&sessionid).is_some()); + Ok(()) + }?; session_write.commit(); } None => { @@ -2024,65 +2017,64 @@ impl<'a> IdmServerProxyWriteTransaction<'a> { } } + #[instrument(level = "debug", skip_all)] pub fn commit(mut self) -> Result<(), OperationError> { - spanned!("idm::server::IdmServerProxyWriteTransaction::commit", { - if self - .qs_write - .get_changed_uuids() - .contains(&UUID_SYSTEM_CONFIG) - { - self.reload_password_badlist()?; - }; - if self.qs_write.get_changed_ouath2() { - self.qs_write - .get_oauth2rs_set() - .and_then(|oauth2rs_set| self.oauth2rs.reload(oauth2rs_set))?; - } - if self.qs_write.get_changed_domain() { - // reload token_key? - self.qs_write - .get_domain_fernet_private_key() - .and_then(|token_key| { - Fernet::new(&token_key).ok_or_else(|| { - admin_error!("Failed to generate token_enc_key"); + if self + .qs_write + .get_changed_uuids() + .contains(&UUID_SYSTEM_CONFIG) + { + self.reload_password_badlist()?; + }; + if self.qs_write.get_changed_ouath2() { + self.qs_write + .get_oauth2rs_set() + .and_then(|oauth2rs_set| self.oauth2rs.reload(oauth2rs_set))?; + } + if self.qs_write.get_changed_domain() { + // reload token_key? + self.qs_write + .get_domain_fernet_private_key() + .and_then(|token_key| { + Fernet::new(&token_key).ok_or_else(|| { + admin_error!("Failed to generate token_enc_key"); + OperationError::InvalidState + }) + }) + .map(|new_handle| { + *self.token_enc_key = new_handle; + })?; + self.qs_write + .get_domain_es256_private_key() + .and_then(|key_der| { + JwsSigner::from_es256_der(&key_der).map_err(|e| { + admin_error!("Failed to generate uat_jwt_signer - {:?}", e); + OperationError::InvalidState + }) + }) + .and_then(|signer| { + signer + .get_validator() + .map_err(|e| { + admin_error!("Failed to generate uat_jwt_validator - {:?}", e); OperationError::InvalidState }) - }) - .map(|new_handle| { - *self.token_enc_key = new_handle; - })?; - self.qs_write - .get_domain_es256_private_key() - .and_then(|key_der| { - JwsSigner::from_es256_der(&key_der).map_err(|e| { - admin_error!("Failed to generate uat_jwt_signer - {:?}", e); - OperationError::InvalidState - }) - }) - .and_then(|signer| { - signer - .get_validator() - .map_err(|e| { - admin_error!("Failed to generate uat_jwt_validator - {:?}", e); - OperationError::InvalidState - }) - .map(|validator| (signer, validator)) - }) - .map(|(new_signer, new_validator)| { - *self.uat_jwt_signer = new_signer; - *self.uat_jwt_validator = new_validator; - })?; - } - // Commit everything. - self.oauth2rs.commit(); - self.uat_jwt_signer.commit(); - self.uat_jwt_validator.commit(); - self.token_enc_key.commit(); - self.pw_badlist_cache.commit(); - self.cred_update_sessions.commit(); - trace!("cred_update_session.commit"); - self.qs_write.commit() - }) + .map(|validator| (signer, validator)) + }) + .map(|(new_signer, new_validator)| { + *self.uat_jwt_signer = new_signer; + *self.uat_jwt_validator = new_validator; + })?; + } + // Commit everything. + self.oauth2rs.commit(); + self.uat_jwt_signer.commit(); + self.uat_jwt_validator.commit(); + self.token_enc_key.commit(); + self.pw_badlist_cache.commit(); + self.cred_update_sessions.commit(); + trace!("cred_update_session.commit"); + self.qs_write.commit() } fn reload_password_badlist(&mut self) -> Result<(), OperationError> { @@ -2100,6 +2092,14 @@ impl<'a> IdmServerProxyWriteTransaction<'a> { #[cfg(test)] mod tests { + use std::convert::TryFrom; + use std::time::Duration; + + use async_std::task; + use kanidm_proto::v1::{AuthAllowed, AuthMech, AuthType, OperationError}; + use smartstring::alias::String as AttrString; + use uuid::Uuid; + use crate::credential::policy::CryptoPolicy; use crate::credential::{Credential, Password}; use crate::event::{AuthEvent, AuthResult, CreateEvent, ModifyEvent}; @@ -2107,20 +2107,12 @@ mod tests { PasswordChangeEvent, RadiusAuthTokenEvent, RegenerateRadiusSecretEvent, UnixGroupTokenEvent, UnixPasswordChangeEvent, UnixUserAuthEvent, UnixUserTokenEvent, }; + use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::idm::AuthState; use crate::modify::{Modify, ModifyList}; use crate::prelude::*; - use kanidm_proto::v1::OperationError; - use kanidm_proto::v1::{AuthAllowed, AuthMech, AuthType}; - - use crate::idm::server::{IdmServer, IdmServerTransaction}; // , IdmServerDelayed; use crate::utils::duration_from_epoch_now; - use async_std::task; - use smartstring::alias::String as AttrString; - use std::convert::TryFrom; - use std::time::Duration; - use uuid::Uuid; const TEST_PASSWORD: &'static str = "ntaoeuntnaoeuhraohuercahu😍"; const TEST_PASSWORD_INC: &'static str = "ntaoentu nkrcgaeunhibwmwmqj;k wqjbkx "; diff --git a/kanidmd/idm/src/idm/serviceaccount.rs b/kanidmd/idm/src/idm/serviceaccount.rs index 18532df8f..67894bbb6 100644 --- a/kanidmd/idm/src/idm/serviceaccount.rs +++ b/kanidmd/idm/src/idm/serviceaccount.rs @@ -1,16 +1,16 @@ +use std::collections::BTreeMap; +use std::time::Duration; + +use compact_jwt::{Jws, JwsSigner}; +use kanidm_proto::v1::ApiToken; +use time::OffsetDateTime; + use crate::event::SearchEvent; use crate::idm::account::Account; use crate::idm::server::{IdmServerProxyReadTransaction, IdmServerProxyWriteTransaction}; use crate::prelude::*; use crate::value::Session; -use compact_jwt::{Jws, JwsSigner}; -use std::collections::BTreeMap; -use std::time::Duration; -use time::OffsetDateTime; - -use kanidm_proto::v1::ApiToken; - // Need to add KID to es256 der for lookups ✅ // Need to generate the es256 on the account on modifies ✅ @@ -87,14 +87,13 @@ pub struct ServiceAccount { } impl ServiceAccount { + #[instrument(level = "debug", skip_all)] pub(crate) fn try_from_entry_rw( value: &Entry, // qs: &mut QueryServerWriteTransaction, ) -> Result { - spanned!("idm::serviceaccount::try_from_entry_rw", { - // let groups = Group::try_from_account_entry_rw(value, qs)?; - try_from_entry!(value) - }) + // let groups = Group::try_from_account_entry_rw(value, qs)?; + try_from_entry!(value) } pub(crate) fn check_api_token_valid( @@ -354,16 +353,17 @@ impl<'a> IdmServerProxyReadTransaction<'a> { #[cfg(test)] mod tests { - use super::{DestroyApiTokenEvent, GenerateApiTokenEvent, GRACE_WINDOW}; - use crate::idm::server::IdmServerTransaction; - // use crate::prelude::*; - - use crate::event::CreateEvent; - use compact_jwt::{Jws, JwsUnverified}; - use kanidm_proto::v1::ApiToken; use std::str::FromStr; use std::time::Duration; + use compact_jwt::{Jws, JwsUnverified}; + use kanidm_proto::v1::ApiToken; + + use super::{DestroyApiTokenEvent, GenerateApiTokenEvent, GRACE_WINDOW}; + // use crate::prelude::*; + use crate::event::CreateEvent; + use crate::idm::server::IdmServerTransaction; + const TEST_CURRENT_TIME: u64 = 6000; #[test] diff --git a/kanidmd/idm/src/idm/unix.rs b/kanidmd/idm/src/idm/unix.rs index bc5831cd5..cb4bcb02c 100644 --- a/kanidmd/idm/src/idm/unix.rs +++ b/kanidmd/idm/src/idm/unix.rs @@ -1,20 +1,18 @@ +use std::iter; +// use crossbeam::channel::Sender; +use std::time::Duration; + +use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken}; +use time::OffsetDateTime; +use tokio::sync::mpsc::UnboundedSender as Sender; use uuid::Uuid; use crate::credential::policy::CryptoPolicy; -use crate::credential::{softlock::CredSoftLockPolicy, Credential}; +use crate::credential::softlock::CredSoftLockPolicy; +use crate::credential::Credential; +use crate::idm::delayed::{DelayedAction, UnixPasswordUpgrade}; use crate::modify::{ModifyInvalid, ModifyList}; use crate::prelude::*; -use kanidm_proto::v1::OperationError; -use kanidm_proto::v1::{UnixGroupToken, UnixUserToken}; - -use crate::idm::delayed::{DelayedAction, UnixPasswordUpgrade}; - -// use crossbeam::channel::Sender; -use std::time::Duration; -use time::OffsetDateTime; -use tokio::sync::mpsc::UnboundedSender as Sender; - -use std::iter; #[derive(Debug, Clone)] pub(crate) struct UnixUserAccount { diff --git a/kanidmd/idm/src/interval.rs b/kanidmd/idm/src/interval.rs index db8737cd6..5a7f37329 100644 --- a/kanidmd/idm/src/interval.rs +++ b/kanidmd/idm/src/interval.rs @@ -1,20 +1,20 @@ //! This contains scheduled tasks/interval tasks that are run inside of the server on a schedule //! as background operations. -use crate::actors::v1_read::QueryServerReadV1; -use crate::actors::v1_write::QueryServerWriteV1; - -use crate::config::OnlineBackup; -use crate::constants::PURGE_FREQUENCY; -use crate::event::{OnlineBackupEvent, PurgeRecycledEvent, PurgeTombstoneEvent}; +use std::fs; +use std::path::Path; use chrono::Utc; use saffron::parse::{CronExpr, English}; use saffron::Cron; -use std::fs; -use std::path::Path; use tokio::time::{interval, sleep, Duration}; +use crate::actors::v1_read::QueryServerReadV1; +use crate::actors::v1_write::QueryServerWriteV1; +use crate::config::OnlineBackup; +use crate::constants::PURGE_FREQUENCY; +use crate::event::{OnlineBackupEvent, PurgeRecycledEvent, PurgeTombstoneEvent}; + pub struct IntervalActor; impl IntervalActor { diff --git a/kanidmd/idm/src/ldap.rs b/kanidmd/idm/src/ldap.rs index f848bcd23..843977673 100644 --- a/kanidmd/idm/src/ldap.rs +++ b/kanidmd/idm/src/ldap.rs @@ -1,18 +1,20 @@ //! LDAP specific operations handling components. This is where LDAP operations //! are sent to for processing. +use std::collections::BTreeSet; +use std::iter; + +use async_std::task; +use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken}; +use ldap3_proto::simple::*; +use regex::Regex; +use tracing::trace; +use uuid::Uuid; + use crate::event::SearchEvent; use crate::idm::event::{LdapAuthEvent, LdapTokenAuthEvent}; use crate::idm::server::{IdmServer, IdmServerTransaction}; use crate::prelude::*; -use async_std::task; -use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken}; -use ldap3_proto::simple::*; -use regex::Regex; -use std::collections::BTreeSet; -use std::iter; -use tracing::trace; -use uuid::Uuid; // Clippy doesn't like Bind here. But proto needs unboxed ldapmsg, // and ldapboundtoken is moved. Really, it's not too bad, every message here is pretty sucky. @@ -121,6 +123,7 @@ impl LdapServer { }) } + #[instrument(level = "debug", skip_all)] async fn do_search( &self, idms: &IdmServer, @@ -252,93 +255,82 @@ impl LdapServer { let ct = duration_from_epoch_now(); let idm_read = idms.proxy_read_async().await; - spanned!("ldap::do_search", { - // Now start the txn - we need it for resolving filter components. + // Now start the txn - we need it for resolving filter components. - // join the filter, with ext_filter - let lfilter = match ext_filter { - Some(ext) => LdapFilter::And(vec![ - sr.filter.clone(), - ext, - LdapFilter::Not(Box::new(LdapFilter::Or(vec![ - LdapFilter::Equality("class".to_string(), "classtype".to_string()), - LdapFilter::Equality("class".to_string(), "attributetype".to_string()), - LdapFilter::Equality( - "class".to_string(), - "access_control_profile".to_string(), - ), - ]))), - ]), - None => LdapFilter::And(vec![ - sr.filter.clone(), - LdapFilter::Not(Box::new(LdapFilter::Or(vec![ - LdapFilter::Equality("class".to_string(), "classtype".to_string()), - LdapFilter::Equality("class".to_string(), "attributetype".to_string()), - LdapFilter::Equality( - "class".to_string(), - "access_control_profile".to_string(), - ), - ]))), - ]), - }; + // join the filter, with ext_filter + let lfilter = match ext_filter { + Some(ext) => LdapFilter::And(vec![ + sr.filter.clone(), + ext, + LdapFilter::Not(Box::new(LdapFilter::Or(vec![ + LdapFilter::Equality("class".to_string(), "classtype".to_string()), + LdapFilter::Equality("class".to_string(), "attributetype".to_string()), + LdapFilter::Equality( + "class".to_string(), + "access_control_profile".to_string(), + ), + ]))), + ]), + None => LdapFilter::And(vec![ + sr.filter.clone(), + LdapFilter::Not(Box::new(LdapFilter::Or(vec![ + LdapFilter::Equality("class".to_string(), "classtype".to_string()), + LdapFilter::Equality("class".to_string(), "attributetype".to_string()), + LdapFilter::Equality( + "class".to_string(), + "access_control_profile".to_string(), + ), + ]))), + ]), + }; - admin_info!(filter = ?lfilter, "LDAP Search Filter"); + admin_info!(filter = ?lfilter, "LDAP Search Filter"); - // Build the event, with the permissions from effective_session - // - // ! Remember, searchEvent wraps to ignore hidden for us. - let se = spanned!("ldap::do_search", { - let ident = idm_read - .validate_ldap_session(&uat.effective_session, ct) - .map_err(|e| { - admin_error!("Invalid identity: {:?}", e); - e - })?; - SearchEvent::new_ext_impersonate_uuid( - &idm_read.qs_read, - ident, - &lfilter, - k_attrs, - ) - }) + // Build the event, with the permissions from effective_session + // + // ! Remember, searchEvent wraps to ignore hidden for us. + let ident = idm_read + .validate_ldap_session(&uat.effective_session, ct) .map_err(|e| { - admin_error!("failed to create search event -> {:?}", e); + admin_error!("Invalid identity: {:?}", e); e })?; + let se = + SearchEvent::new_ext_impersonate_uuid(&idm_read.qs_read, ident, &lfilter, k_attrs) + .map_err(|e| { + admin_error!("failed to create search event -> {:?}", e); + e + })?; - let res = idm_read.qs_read.search_ext(&se).map_err(|e| { - admin_error!("search failure {:?}", e); - e - })?; + let res = idm_read.qs_read.search_ext(&se).map_err(|e| { + admin_error!("search failure {:?}", e); + e + })?; - // These have already been fully reduced (access controls applied), - // so we can just transform the values and open palm slam them into - // the result structure. - let lres = spanned!("ldap::do_search", { - let lres: Result, _> = res - .into_iter() - .map(|e| { - e.to_ldap(&idm_read.qs_read, self.basedn.as_str(), all_attrs, &l_attrs) - // if okay, wrap in a ldap msg. - .map(|r| sr.gen_result_entry(r)) - }) - .chain(iter::once(Ok(sr.gen_success()))) - .collect(); - lres - }); + // These have already been fully reduced (access controls applied), + // so we can just transform the values and open palm slam them into + // the result structure. + let lres: Result, _> = res + .into_iter() + .map(|e| { + e.to_ldap(&idm_read.qs_read, self.basedn.as_str(), all_attrs, &l_attrs) + // if okay, wrap in a ldap msg. + .map(|r| sr.gen_result_entry(r)) + }) + .chain(iter::once(Ok(sr.gen_success()))) + .collect(); - let lres = lres.map_err(|e| { - admin_error!("entry resolve failure {:?}", e); - e - })?; + let lres = lres.map_err(|e| { + admin_error!("entry resolve failure {:?}", e); + e + })?; - admin_info!( - nentries = %lres.len(), - "LDAP Search Success -> number of entries" - ); + admin_info!( + nentries = %lres.len(), + "LDAP Search Success -> number of entries" + ); - Ok(lres) - }) + Ok(lres) } } @@ -550,18 +542,19 @@ pub(crate) fn ldap_attr_filter_map(input: &str) -> AttrString { #[cfg(test)] mod tests { // use crate::prelude::*; - use crate::event::{CreateEvent, ModifyEvent}; - use crate::idm::event::UnixPasswordChangeEvent; - use crate::idm::serviceaccount::GenerateApiTokenEvent; - use crate::ldap::{LdapServer, LdapSession}; + use std::str::FromStr; + use async_std::task; + use compact_jwt::{Jws, JwsUnverified}; use hashbrown::HashSet; use kanidm_proto::v1::ApiToken; use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope}; use ldap3_proto::simple::*; - use std::str::FromStr; - use compact_jwt::{Jws, JwsUnverified}; + use crate::event::{CreateEvent, ModifyEvent}; + use crate::idm::event::UnixPasswordChangeEvent; + use crate::idm::serviceaccount::GenerateApiTokenEvent; + use crate::ldap::{LdapServer, LdapSession}; const TEST_PASSWORD: &'static str = "ntaoeuntnaoeuhraohuercahu😍"; diff --git a/kanidmd/idm/src/lib.rs b/kanidmd/idm/src/lib.rs index 1fe22dd86..3112e9ee8 100644 --- a/kanidmd/idm/src/lib.rs +++ b/kanidmd/idm/src/lib.rs @@ -63,39 +63,36 @@ pub mod config; /// A prelude of imports that should be imported by all other Kanidm modules to /// help make imports cleaner. pub mod prelude { - pub use crate::utils::duration_from_epoch_now; pub use kanidm_proto::v1::{ConsistencyError, OperationError}; + pub use sketching::{ + admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace, + filter_warn, perf_trace, request_error, request_info, request_trace, request_warn, + security_access, security_critical, security_error, security_info, tagged_event, EventTag, + }; pub use smartstring::alias::String as AttrString; pub use url::Url; pub use uuid::Uuid; pub use crate::constants::*; - pub use crate::filter::{ - f_and, f_andnot, f_eq, f_id, f_inc, f_lt, f_or, f_pres, f_self, f_spn_name, f_sub, - }; - pub use crate::filter::{Filter, FilterInvalid, FC}; - pub use crate::modify::{m_pres, m_purge, m_remove}; - pub use crate::modify::{Modify, ModifyInvalid, ModifyList}; - pub use crate::entry::{ Entry, EntryCommitted, EntryInit, EntryInvalid, EntryInvalidCommitted, EntryNew, EntryReduced, EntrySealed, EntrySealedCommitted, EntryTuple, EntryValid, }; + pub use crate::filter::{ + f_and, f_andnot, f_eq, f_id, f_inc, f_lt, f_or, f_pres, f_self, f_spn_name, f_sub, Filter, + FilterInvalid, FC, + }; pub use crate::identity::Identity; + pub use crate::modify::{m_pres, m_purge, m_remove, Modify, ModifyInvalid, ModifyList}; pub use crate::server::{ QueryServer, QueryServerReadTransaction, QueryServerTransaction, QueryServerWriteTransaction, }; + pub use crate::utils::duration_from_epoch_now; pub use crate::value::{IndexType, PartialValue, SyntaxType, Value}; pub use crate::valueset::{ ValueSet, ValueSetBool, ValueSetCid, ValueSetIndex, ValueSetIutf8, ValueSetRefer, ValueSetSecret, ValueSetSpn, ValueSetSyntax, ValueSetT, ValueSetUint32, ValueSetUtf8, ValueSetUuid, }; - pub use sketching::{ - admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace, - filter_warn, perf_trace, request_error, request_info, request_trace, request_warn, - security_access, security_critical, security_error, security_info, spanned, tagged_event, - EventTag, - }; } diff --git a/kanidmd/idm/src/macros.rs b/kanidmd/idm/src/macros.rs index 88d16bccf..b497ddd8c 100644 --- a/kanidmd/idm/src/macros.rs +++ b/kanidmd/idm/src/macros.rs @@ -19,9 +19,10 @@ macro_rules! setup_test { ( $preload_entries:expr ) => {{ - use crate::utils::duration_from_epoch_now; use async_std::task; + use crate::utils::duration_from_epoch_now; + let _ = sketching::test_init(); // Create an in memory BE @@ -105,10 +106,11 @@ macro_rules! run_test { #[cfg(test)] macro_rules! entry_str_to_account { ($entry_str:expr) => {{ + use std::iter::once; + use crate::entry::{Entry, EntryInvalid, EntryNew}; use crate::idm::account::Account; use crate::value::Value; - use std::iter::once; let mut e: Entry = unsafe { Entry::unsafe_from_entry_str($entry_str).into_invalid_new() }; @@ -195,37 +197,35 @@ macro_rules! run_create_test { use crate::schema::Schema; use crate::utils::duration_from_epoch_now; - spanned!("plugins::macros::run_create_test", { - let qs = setup_test!($preload_entries); + let qs = setup_test!($preload_entries); - let ce = match $internal { - None => CreateEvent::new_internal($create_entries.clone()), - Some(e_str) => unsafe { - CreateEvent::new_impersonate_entry_ser(e_str, $create_entries.clone()) - }, - }; + let ce = match $internal { + None => CreateEvent::new_internal($create_entries.clone()), + Some(e_str) => unsafe { + CreateEvent::new_impersonate_entry_ser(e_str, $create_entries.clone()) + }, + }; - { - let qs_write = qs.write(duration_from_epoch_now()); - let r = qs_write.create(&ce); - trace!("test result: {:?}", r); - assert!(r == $expect); - $check(&qs_write); - match r { - Ok(_) => { - qs_write.commit().expect("commit failure!"); - } - Err(e) => { - admin_error!("Rolling back => {:?}", e); - } + { + let qs_write = qs.write(duration_from_epoch_now()); + let r = qs_write.create(&ce); + trace!("test result: {:?}", r); + assert!(r == $expect); + $check(&qs_write); + match r { + Ok(_) => { + qs_write.commit().expect("commit failure!"); + } + Err(e) => { + admin_error!("Rolling back => {:?}", e); } } - // Make sure there are no errors. - trace!("starting verification"); - let ver = qs.verify(); - trace!("verification -> {:?}", ver); - assert!(ver.len() == 0); - }); + } + // Make sure there are no errors. + trace!("starting verification"); + let ver = qs.verify(); + trace!("verification -> {:?}", ver); + assert!(ver.len() == 0); }}; } @@ -246,49 +246,41 @@ macro_rules! run_modify_test { use crate::prelude::*; use crate::schema::Schema; - spanned!("plugins::macros::run_modify_test", { - let qs = setup_test!($preload_entries); + let qs = setup_test!($preload_entries); - { - let qs_write = qs.write(duration_from_epoch_now()); - spanned!("plugins::macros::run_modify_test -> pre_test hook", { - $pre_hook(&qs_write) - }); - qs_write.commit().expect("commit failure!"); - } + { + let qs_write = qs.write(duration_from_epoch_now()); + $pre_hook(&qs_write); + qs_write.commit().expect("commit failure!"); + } - let me = match $internal { - None => unsafe { ModifyEvent::new_internal_invalid($modify_filter, $modify_list) }, - Some(e_str) => unsafe { - ModifyEvent::new_impersonate_entry_ser(e_str, $modify_filter, $modify_list) - }, - }; + let me = match $internal { + None => unsafe { ModifyEvent::new_internal_invalid($modify_filter, $modify_list) }, + Some(e_str) => unsafe { + ModifyEvent::new_impersonate_entry_ser(e_str, $modify_filter, $modify_list) + }, + }; - { - let qs_write = qs.write(duration_from_epoch_now()); - let r = spanned!("plugins::macros::run_modify_test -> main_test", { - qs_write.modify(&me) - }); - spanned!("plugins::macros::run_modify_test -> post_test check", { - $check(&qs_write) - }); - trace!("test result: {:?}", r); - assert!(r == $expect); - match r { - Ok(_) => { - qs_write.commit().expect("commit failure!"); - } - Err(e) => { - admin_error!("Rolling back => {:?}", e); - } + { + let qs_write = qs.write(duration_from_epoch_now()); + let r = qs_write.modify(&me); + $check(&qs_write); + trace!("test result: {:?}", r); + assert!(r == $expect); + match r { + Ok(_) => { + qs_write.commit().expect("commit failure!"); + } + Err(e) => { + admin_error!("Rolling back => {:?}", e); } } - // Make sure there are no errors. - trace!("starting verification"); - let ver = qs.verify(); - trace!("verification -> {:?}", ver); - assert!(ver.len() == 0); - }); + } + // Make sure there are no errors. + trace!("starting verification"); + let ver = qs.verify(); + trace!("verification -> {:?}", ver); + assert!(ver.len() == 0); }}; } @@ -308,37 +300,35 @@ macro_rules! run_delete_test { use crate::schema::Schema; use crate::utils::duration_from_epoch_now; - spanned!("plugins::macros::run_delete_test", { - let qs = setup_test!($preload_entries); + let qs = setup_test!($preload_entries); - let de = match $internal { - Some(e_str) => unsafe { - DeleteEvent::new_impersonate_entry_ser(e_str, $delete_filter.clone()) - }, - None => unsafe { DeleteEvent::new_internal_invalid($delete_filter.clone()) }, - }; + let de = match $internal { + Some(e_str) => unsafe { + DeleteEvent::new_impersonate_entry_ser(e_str, $delete_filter.clone()) + }, + None => unsafe { DeleteEvent::new_internal_invalid($delete_filter.clone()) }, + }; - { - let qs_write = qs.write(duration_from_epoch_now()); - let r = qs_write.delete(&de); - trace!("test result: {:?}", r); - $check(&qs_write); - assert!(r == $expect); - match r { - Ok(_) => { - qs_write.commit().expect("commit failure!"); - } - Err(e) => { - admin_error!("Rolling back => {:?}", e); - } + { + let qs_write = qs.write(duration_from_epoch_now()); + let r = qs_write.delete(&de); + trace!("test result: {:?}", r); + $check(&qs_write); + assert!(r == $expect); + match r { + Ok(_) => { + qs_write.commit().expect("commit failure!"); + } + Err(e) => { + admin_error!("Rolling back => {:?}", e); } } - // Make sure there are no errors. - trace!("starting verification"); - let ver = qs.verify(); - trace!("verification -> {:?}", ver); - assert!(ver.len() == 0); - }); + } + // Make sure there are no errors. + trace!("starting verification"); + let ver = qs.verify(); + trace!("verification -> {:?}", ver); + assert!(ver.len() == 0); }}; } diff --git a/kanidmd/idm/src/modify.rs b/kanidmd/idm/src/modify.rs index 189be742f..c1fba5005 100644 --- a/kanidmd/idm/src/modify.rs +++ b/kanidmd/idm/src/modify.rs @@ -2,19 +2,19 @@ //! express the series of Modifications that should be applied. These are expressed //! as "states" on what attribute-values should appear as within the `Entry` -use crate::prelude::*; -use kanidm_proto::v1::Entry as ProtoEntry; -use kanidm_proto::v1::Modify as ProtoModify; -use kanidm_proto::v1::ModifyList as ProtoModifyList; - -use crate::schema::SchemaTransaction; -use crate::value::{PartialValue, Value}; -use kanidm_proto::v1::{OperationError, SchemaError}; +use std::slice; +use kanidm_proto::v1::{ + Entry as ProtoEntry, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError, + SchemaError, +}; // Should this be std? use serde::{Deserialize, Serialize}; use smartstring::alias::String as AttrString; -use std::slice; + +use crate::prelude::*; +use crate::schema::SchemaTransaction; +use crate::value::{PartialValue, Value}; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ModifyValid; @@ -69,8 +69,8 @@ pub struct ModifyList { } impl<'a> IntoIterator for &'a ModifyList { - type Item = &'a Modify; type IntoIter = slice::Iter<'a, Modify>; + type Item = &'a Modify; fn into_iter(self) -> Self::IntoIter { self.mods.iter() diff --git a/kanidmd/idm/src/plugins/attrunique.rs b/kanidmd/idm/src/plugins/attrunique.rs index edcc139d3..d74bc4891 100644 --- a/kanidmd/idm/src/plugins/attrunique.rs +++ b/kanidmd/idm/src/plugins/attrunique.rs @@ -4,14 +4,15 @@ // both change approaches. // // +use std::collections::BTreeMap; + +use kanidm_proto::v1::{ConsistencyError, PluginError}; +use tracing::trace; + use crate::event::{CreateEvent, ModifyEvent}; use crate::plugins::Plugin; use crate::prelude::*; use crate::schema::SchemaTransaction; -use kanidm_proto::v1::{ConsistencyError, PluginError}; -use tracing::trace; - -use std::collections::BTreeMap; pub struct AttrUnique; @@ -192,9 +193,10 @@ impl Plugin for AttrUnique { #[cfg(test)] mod tests { - use crate::prelude::*; use kanidm_proto::v1::PluginError; + use crate::prelude::*; + // Test entry in db, and same name, reject. #[test] fn test_pre_create_name_unique() { diff --git a/kanidmd/idm/src/plugins/base.rs b/kanidmd/idm/src/plugins/base.rs index 12ba64f7f..a60ced3c2 100644 --- a/kanidmd/idm/src/plugins/base.rs +++ b/kanidmd/idm/src/plugins/base.rs @@ -1,12 +1,13 @@ -use crate::plugins::Plugin; -use hashbrown::HashSet; use std::collections::BTreeSet; use std::iter::once; +use hashbrown::HashSet; +use kanidm_proto::v1::{ConsistencyError, PluginError}; + use crate::event::{CreateEvent, ModifyEvent}; use crate::modify::Modify; +use crate::plugins::Plugin; use crate::prelude::*; -use kanidm_proto::v1::{ConsistencyError, PluginError}; lazy_static! { static ref CLASS_OBJECT: Value = Value::new_class("object"); @@ -43,15 +44,9 @@ impl Plugin for Base { // debug!("Entering base pre_create_transform"); // For each candidate for entry in cand.iter_mut() { - trace!("Base check on entry: {:?}", entry); - // First, ensure we have the 'object', class in the class set. entry.add_ava("class", CLASS_OBJECT.clone()); - trace!("Object should now be in entry: {:?}", entry); - - // If they have a name, but no principal name, derive it. - // if they don't have uuid, create it. match entry.get_ava_set("uuid").map(|s| s.len()) { None => { @@ -85,7 +80,6 @@ impl Plugin for Base { let uuid_ref: Uuid = entry .get_ava_single_uuid("uuid") .ok_or_else(|| OperationError::InvalidAttribute("uuid".to_string()))?; - trace!("Entry valid UUID: {:?}", entry); if !cand_uuid.insert(uuid_ref) { trace!("uuid duplicate found in create set! {:?}", uuid_ref); return Err(OperationError::Plugin(PluginError::Base( @@ -224,9 +218,10 @@ impl Plugin for Base { #[cfg(test)] mod tests { - use crate::prelude::*; use kanidm_proto::v1::PluginError; + use crate::prelude::*; + const JSON_ADMIN_ALLOW_ALL: &'static str = r#"{ "attrs": { "class": [ diff --git a/kanidmd/idm/src/plugins/domain.rs b/kanidmd/idm/src/plugins/domain.rs index eca3c41bb..1bd1774da 100644 --- a/kanidmd/idm/src/plugins/domain.rs +++ b/kanidmd/idm/src/plugins/domain.rs @@ -4,15 +4,16 @@ // The primary point of this is to generate a unique domain UUID on startup // which is importart for management of the replication topo and trust // relationships. -use crate::plugins::Plugin; +use std::iter::once; -use crate::event::{CreateEvent, ModifyEvent}; -use crate::prelude::*; use compact_jwt::JwsSigner; use kanidm_proto::v1::OperationError; -use std::iter::once; use tracing::trace; +use crate::event::{CreateEvent, ModifyEvent}; +use crate::plugins::Plugin; +use crate::prelude::*; + lazy_static! { static ref PVCLASS_DOMAIN_INFO: PartialValue = PartialValue::new_class("domain_info"); static ref PVUUID_DOMAIN_INFO: PartialValue = PartialValue::new_uuid(*UUID_DOMAIN_INFO); diff --git a/kanidmd/idm/src/plugins/dyngroup.rs b/kanidmd/idm/src/plugins/dyngroup.rs index c890216ee..d4956fea2 100644 --- a/kanidmd/idm/src/plugins/dyngroup.rs +++ b/kanidmd/idm/src/plugins/dyngroup.rs @@ -1,9 +1,11 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + +use kanidm_proto::v1::Filter as ProtoFilter; + use crate::event::{CreateEvent, ModifyEvent}; use crate::filter::FilterInvalid; use crate::prelude::*; -use kanidm_proto::v1::Filter as ProtoFilter; -use std::collections::BTreeMap; -use std::sync::Arc; lazy_static! { static ref CLASS_DYNGROUP: PartialValue = PartialValue::new_class("dyngroup"); @@ -361,9 +363,10 @@ impl DynGroup { #[cfg(test)] mod tests { - use crate::prelude::*; use kanidm_proto::v1::Filter as ProtoFilter; + use crate::prelude::*; + const UUID_TEST_GROUP: Uuid = uuid::uuid!("7bfd9931-06c2-4608-8a46-78719bb746fe"); #[test] diff --git a/kanidmd/idm/src/plugins/gidnumber.rs b/kanidmd/idm/src/plugins/gidnumber.rs index b491f7c29..b81dbc073 100644 --- a/kanidmd/idm/src/plugins/gidnumber.rs +++ b/kanidmd/idm/src/plugins/gidnumber.rs @@ -1,11 +1,12 @@ // A plugin that generates gid numbers on types that require them for posix // support. +use std::iter::once; + use crate::event::{CreateEvent, ModifyEvent}; use crate::plugins::Plugin; use crate::prelude::*; use crate::utils::uuid_to_gid_u32; -use std::iter::once; /// Systemd dynamic units allocate between 61184–65519, most distros allocate /// system uids from 0 - 1000, and many others give user ids between 1000 to diff --git a/kanidmd/idm/src/plugins/jwskeygen.rs b/kanidmd/idm/src/plugins/jwskeygen.rs index b5974024e..6b9ed4056 100644 --- a/kanidmd/idm/src/plugins/jwskeygen.rs +++ b/kanidmd/idm/src/plugins/jwskeygen.rs @@ -1,8 +1,9 @@ +use compact_jwt::JwsSigner; + use crate::event::{CreateEvent, ModifyEvent}; use crate::plugins::Plugin; use crate::prelude::*; use crate::utils::password_from_random; -use compact_jwt::JwsSigner; lazy_static! { static ref CLASS_OAUTH2_BASIC: PartialValue = diff --git a/kanidmd/idm/src/plugins/memberof.rs b/kanidmd/idm/src/plugins/memberof.rs index ab1c37548..2485ea754 100644 --- a/kanidmd/idm/src/plugins/memberof.rs +++ b/kanidmd/idm/src/plugins/memberof.rs @@ -10,16 +10,17 @@ // As a result, we first need to run refint to clean up all dangling references, then memberof // fixes the graph of memberships +use std::collections::BTreeSet; +use std::sync::Arc; + +use hashbrown::HashMap; +use kanidm_proto::v1::{ConsistencyError, OperationError}; + use crate::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::plugins::Plugin; use crate::prelude::*; use crate::value::{PartialValue, Value}; -use kanidm_proto::v1::{ConsistencyError, OperationError}; -use std::collections::BTreeSet; - -use hashbrown::HashMap; -use std::sync::Arc; lazy_static! { static ref CLASS_GROUP: PartialValue = PartialValue::new_class("group"); diff --git a/kanidmd/idm/src/plugins/mod.rs b/kanidmd/idm/src/plugins/mod.rs index d49197430..f38597ca4 100644 --- a/kanidmd/idm/src/plugins/mod.rs +++ b/kanidmd/idm/src/plugins/mod.rs @@ -3,12 +3,13 @@ //! helps to ensure that data is always in specific known states within the //! `QueryServer` +use std::sync::Arc; + +use kanidm_proto::v1::{ConsistencyError, OperationError}; + use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::prelude::*; -use kanidm_proto::v1::{ConsistencyError, OperationError}; -use std::sync::Arc; -use tracing::trace_span; mod attrunique; mod base; @@ -118,108 +119,99 @@ macro_rules! run_verify_plugin { } impl Plugins { + #[instrument(level = "debug", name = "plugins::run_pre_create_transform", skip_all)] pub fn run_pre_create_transform( qs: &QueryServerWriteTransaction, cand: &mut Vec>, ce: &CreateEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_pre_create_transform", { - base::Base::pre_create_transform(qs, cand, ce) - .and_then(|_| password_import::PasswordImport::pre_create_transform(qs, cand, ce)) - .and_then(|_| jwskeygen::JwsKeygen::pre_create_transform(qs, cand, ce)) - .and_then(|_| gidnumber::GidNumber::pre_create_transform(qs, cand, ce)) - .and_then(|_| domain::Domain::pre_create_transform(qs, cand, ce)) - .and_then(|_| spn::Spn::pre_create_transform(qs, cand, ce)) - // Should always be last - .and_then(|_| attrunique::AttrUnique::pre_create_transform(qs, cand, ce)) - }) + base::Base::pre_create_transform(qs, cand, ce) + .and_then(|_| password_import::PasswordImport::pre_create_transform(qs, cand, ce)) + .and_then(|_| jwskeygen::JwsKeygen::pre_create_transform(qs, cand, ce)) + .and_then(|_| gidnumber::GidNumber::pre_create_transform(qs, cand, ce)) + .and_then(|_| domain::Domain::pre_create_transform(qs, cand, ce)) + .and_then(|_| spn::Spn::pre_create_transform(qs, cand, ce)) + // Should always be last + .and_then(|_| attrunique::AttrUnique::pre_create_transform(qs, cand, ce)) } + #[instrument(level = "debug", name = "plugins::run_pre_create", skip_all)] pub fn run_pre_create( qs: &QueryServerWriteTransaction, cand: &[Entry], ce: &CreateEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_pre_create", { - protected::Protected::pre_create(qs, cand, ce) - }) + protected::Protected::pre_create(qs, cand, ce) } + #[instrument(level = "debug", name = "plugins::run_post_create", skip_all)] pub fn run_post_create( qs: &QueryServerWriteTransaction, cand: &[Entry], ce: &CreateEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_post_create", { - refint::ReferentialIntegrity::post_create(qs, cand, ce) - .and_then(|_| memberof::MemberOf::post_create(qs, cand, ce)) - }) + refint::ReferentialIntegrity::post_create(qs, cand, ce) + .and_then(|_| memberof::MemberOf::post_create(qs, cand, ce)) } + #[instrument(level = "debug", name = "plugins::run_pre_modify", skip_all)] pub fn run_pre_modify( qs: &QueryServerWriteTransaction, cand: &mut Vec>, me: &ModifyEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_pre_modify", { - protected::Protected::pre_modify(qs, cand, me) - .and_then(|_| base::Base::pre_modify(qs, cand, me)) - .and_then(|_| password_import::PasswordImport::pre_modify(qs, cand, me)) - .and_then(|_| jwskeygen::JwsKeygen::pre_modify(qs, cand, me)) - .and_then(|_| gidnumber::GidNumber::pre_modify(qs, cand, me)) - .and_then(|_| domain::Domain::pre_modify(qs, cand, me)) - .and_then(|_| spn::Spn::pre_modify(qs, cand, me)) - // attr unique should always be last - .and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me)) - }) + protected::Protected::pre_modify(qs, cand, me) + .and_then(|_| base::Base::pre_modify(qs, cand, me)) + .and_then(|_| password_import::PasswordImport::pre_modify(qs, cand, me)) + .and_then(|_| jwskeygen::JwsKeygen::pre_modify(qs, cand, me)) + .and_then(|_| gidnumber::GidNumber::pre_modify(qs, cand, me)) + .and_then(|_| domain::Domain::pre_modify(qs, cand, me)) + .and_then(|_| spn::Spn::pre_modify(qs, cand, me)) + // attr unique should always be last + .and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me)) } + #[instrument(level = "debug", name = "plugins::run_post_modify", skip_all)] pub fn run_post_modify( qs: &QueryServerWriteTransaction, pre_cand: &[Arc>], cand: &[Entry], me: &ModifyEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_post_modify", { - refint::ReferentialIntegrity::post_modify(qs, pre_cand, cand, me) - .and_then(|_| spn::Spn::post_modify(qs, pre_cand, cand, me)) - .and_then(|_| memberof::MemberOf::post_modify(qs, pre_cand, cand, me)) - }) + refint::ReferentialIntegrity::post_modify(qs, pre_cand, cand, me) + .and_then(|_| spn::Spn::post_modify(qs, pre_cand, cand, me)) + .and_then(|_| memberof::MemberOf::post_modify(qs, pre_cand, cand, me)) } + #[instrument(level = "debug", name = "plugins::run_pre_delete", skip_all)] pub fn run_pre_delete( qs: &QueryServerWriteTransaction, cand: &mut Vec>, de: &DeleteEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_pre_delete", { - protected::Protected::pre_delete(qs, cand, de) - }) + protected::Protected::pre_delete(qs, cand, de) } + #[instrument(level = "debug", name = "plugins::run_post_delete", skip_all)] pub fn run_post_delete( qs: &QueryServerWriteTransaction, cand: &[Entry], de: &DeleteEvent, ) -> Result<(), OperationError> { - spanned!("plugins::run_post_delete", { - refint::ReferentialIntegrity::post_delete(qs, cand, de) - .and_then(|_| memberof::MemberOf::post_delete(qs, cand, de)) - }) + refint::ReferentialIntegrity::post_delete(qs, cand, de) + .and_then(|_| memberof::MemberOf::post_delete(qs, cand, de)) } + #[instrument(level = "debug", name = "plugins::run_verify", skip_all)] pub fn run_verify( qs: &QueryServerReadTransaction, results: &mut Vec>, ) { - let _entered = trace_span!("plugins::run_verify").entered(); - spanned!("plugins::run_verify", { - run_verify_plugin!(qs, results, base::Base); - run_verify_plugin!(qs, results, attrunique::AttrUnique); - run_verify_plugin!(qs, results, refint::ReferentialIntegrity); - run_verify_plugin!(qs, results, dyngroup::DynGroup); - run_verify_plugin!(qs, results, memberof::MemberOf); - run_verify_plugin!(qs, results, spn::Spn); - }) + run_verify_plugin!(qs, results, base::Base); + run_verify_plugin!(qs, results, attrunique::AttrUnique); + run_verify_plugin!(qs, results, refint::ReferentialIntegrity); + run_verify_plugin!(qs, results, dyngroup::DynGroup); + run_verify_plugin!(qs, results, memberof::MemberOf); + run_verify_plugin!(qs, results, spn::Spn); } } diff --git a/kanidmd/idm/src/plugins/password_import.rs b/kanidmd/idm/src/plugins/password_import.rs index cd1f31dad..50a1cd2bd 100644 --- a/kanidmd/idm/src/plugins/password_import.rs +++ b/kanidmd/idm/src/plugins/password_import.rs @@ -1,11 +1,13 @@ // Transform password import requests into proper kanidm credentials. +use std::convert::TryFrom; +use std::iter::once; + +use kanidm_proto::v1::PluginError; + use crate::credential::{Credential, Password}; use crate::event::{CreateEvent, ModifyEvent}; use crate::plugins::Plugin; use crate::prelude::*; -use kanidm_proto::v1::PluginError; -use std::convert::TryFrom; -use std::iter::once; pub struct PasswordImport {} diff --git a/kanidmd/idm/src/plugins/protected.rs b/kanidmd/idm/src/plugins/protected.rs index edddc875c..53d028346 100644 --- a/kanidmd/idm/src/plugins/protected.rs +++ b/kanidmd/idm/src/plugins/protected.rs @@ -1,12 +1,12 @@ // System protected objects. Items matching specific requirements // may only have certain modifications performed. -use crate::plugins::Plugin; -use crate::prelude::*; +use hashbrown::HashSet; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::modify::Modify; -use hashbrown::HashSet; +use crate::plugins::Plugin; +use crate::prelude::*; pub struct Protected {} diff --git a/kanidmd/idm/src/plugins/refint.rs b/kanidmd/idm/src/plugins/refint.rs index be6730de4..f3d251589 100644 --- a/kanidmd/idm/src/plugins/refint.rs +++ b/kanidmd/idm/src/plugins/refint.rs @@ -9,19 +9,19 @@ // when that is written, as they *both* manipulate and alter entry reference // data, so we should be careful not to step on each other. -use hashbrown::HashSet as Set; use std::collections::BTreeSet; +use std::sync::Arc; -use crate::plugins::Plugin; -use crate::prelude::*; +use hashbrown::HashSet as Set; +use kanidm_proto::v1::{ConsistencyError, PluginError}; +use tracing::trace; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::filter::f_eq; use crate::modify::Modify; +use crate::plugins::Plugin; +use crate::prelude::*; use crate::schema::SchemaTransaction; -use kanidm_proto::v1::{ConsistencyError, PluginError}; -use std::sync::Arc; -use tracing::trace; // NOTE: This *must* be after base.rs!!! @@ -265,9 +265,10 @@ impl Plugin for ReferentialIntegrity { #[cfg(test)] mod tests { - use crate::prelude::*; use kanidm_proto::v1::PluginError; + use crate::prelude::*; + // The create references a uuid that doesn't exist - reject #[test] fn test_create_uuid_reference_not_exist() { diff --git a/kanidmd/idm/src/plugins/spn.rs b/kanidmd/idm/src/plugins/spn.rs index b553503b5..70b9ad915 100644 --- a/kanidmd/idm/src/plugins/spn.rs +++ b/kanidmd/idm/src/plugins/spn.rs @@ -1,16 +1,17 @@ // Generate and manage spn's for all entries in the domain. Also deals with // the infrequent - but possible - case where a domain is renamed. -use crate::plugins::Plugin; -use crate::prelude::*; +use std::iter::once; +use std::sync::Arc; + +// use crate::value::{PartialValue, Value}; +use kanidm_proto::v1::{ConsistencyError, OperationError}; use crate::constants::UUID_DOMAIN_INFO; use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::event::{CreateEvent, ModifyEvent}; +use crate::plugins::Plugin; +use crate::prelude::*; use crate::value::PartialValue; -// use crate::value::{PartialValue, Value}; -use kanidm_proto::v1::{ConsistencyError, OperationError}; -use std::iter::once; -use std::sync::Arc; pub struct Spn {} diff --git a/kanidmd/idm/src/repl/cid.rs b/kanidmd/idm/src/repl/cid.rs index 503d0f053..65f675903 100644 --- a/kanidmd/idm/src/repl/cid.rs +++ b/kanidmd/idm/src/repl/cid.rs @@ -1,7 +1,8 @@ -use kanidm_proto::v1::OperationError; -use serde::{Deserialize, Serialize}; use std::fmt; use std::time::Duration; + +use kanidm_proto::v1::OperationError; +use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)] @@ -73,11 +74,13 @@ impl Cid { #[cfg(test)] mod tests { - use crate::repl::cid::Cid; use std::cmp::Ordering; use std::time::Duration; + use uuid::Uuid; + use crate::repl::cid::Cid; + #[test] fn test_cid_ordering() { // Check diff ts diff --git a/kanidmd/idm/src/repl/entry.rs b/kanidmd/idm/src/repl/entry.rs index e2dc5e057..4eb2e3a88 100644 --- a/kanidmd/idm/src/repl/entry.rs +++ b/kanidmd/idm/src/repl/entry.rs @@ -1,18 +1,17 @@ -use super::cid::Cid; -use crate::prelude::*; -use crate::valueset; -use kanidm_proto::v1::ConsistencyError; - -use crate::entry::{compare_attrs, Eattrs}; -use crate::schema::SchemaTransaction; - use std::collections::btree_map::Keys; use std::collections::BTreeMap; - use std::fmt; use std::ops::Bound; use std::ops::Bound::*; +use kanidm_proto::v1::ConsistencyError; + +use super::cid::Cid; +use crate::entry::{compare_attrs, Eattrs}; +use crate::prelude::*; +use crate::schema::SchemaTransaction; +use crate::valueset; + lazy_static! { static ref PVCLASS_TOMBSTONE: PartialValue = PartialValue::new_class("tombstone"); static ref PVCLASS_RECYCLED: PartialValue = PartialValue::new_class("recycled"); @@ -518,12 +517,13 @@ impl EntryChangelog { #[cfg(test)] mod tests { + use std::time::Duration; + use crate::entry::Eattrs; // use crate::prelude::*; use crate::repl::cid::Cid; use crate::repl::entry::{Change, EntryChangelog, State, Transition}; use crate::schema::{Schema, SchemaTransaction}; - use std::time::Duration; #[test] fn test_entrychangelog_basic() { diff --git a/kanidmd/idm/src/repl/ruv.rs b/kanidmd/idm/src/repl/ruv.rs index e07064ab9..f02ad3efc 100644 --- a/kanidmd/idm/src/repl/ruv.rs +++ b/kanidmd/idm/src/repl/ruv.rs @@ -1,13 +1,15 @@ -use crate::prelude::*; -use crate::repl::cid::Cid; -use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn}; -use idlset::v2::IDLBitRange; -use kanidm_proto::v1::ConsistencyError; use std::cmp::Ordering; use std::collections::BTreeMap; use std::ops::Bound::*; use std::sync::Arc; +use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn}; +use idlset::v2::IDLBitRange; +use kanidm_proto::v1::ConsistencyError; + +use crate::prelude::*; +use crate::repl::cid::Cid; + pub struct ReplicationUpdateVector { // This sorts by time. Should we look up by IDL or by UUID? // I think IDL, because when we need to actually do the look ups we'll need diff --git a/kanidmd/idm/src/schema.rs b/kanidmd/idm/src/schema.rs index c3924c763..8f027df5a 100644 --- a/kanidmd/idm/src/schema.rs +++ b/kanidmd/idm/src/schema.rs @@ -16,17 +16,17 @@ //! [`Attributes`]: struct.SchemaAttribute.html //! [`Classes`]: struct.SchemaClass.html +use std::collections::BTreeSet; + +use concread::cowcell::*; +use hashbrown::{HashMap, HashSet}; +use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError}; +use tracing::trace; +use uuid::Uuid; + use crate::be::IdxKey; use crate::prelude::*; use crate::valueset::ValueSet; -use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError}; -use tracing::trace; - -use hashbrown::{HashMap, HashSet}; -use std::collections::BTreeSet; -use uuid::Uuid; - -use concread::cowcell::*; // representations of schema that confines object types, classes // and attributes. This ties in deeply with "Entry". @@ -642,124 +642,124 @@ impl<'a> SchemaWriteTransaction<'a> { .collect() } + #[instrument(level = "debug", name = "schema::generate_in_memory", skip_all)] pub fn generate_in_memory(&mut self) -> Result<(), OperationError> { - spanned!("schema::generate_in_memory", { - // - self.classes.clear(); - self.attributes.clear(); - // Bootstrap in definitions of our own schema types - // First, add all the needed core attributes for schema parsing - self.attributes.insert( - AttrString::from("class"), - SchemaAttribute { - name: AttrString::from("class"), - uuid: UUID_SCHEMA_ATTR_CLASS, - description: String::from("The set of classes defining an object"), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality, IndexType::Presence], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("uuid"), - SchemaAttribute { - name: AttrString::from("uuid"), - uuid: UUID_SCHEMA_ATTR_UUID, - description: String::from("The universal unique id of the object"), - multivalue: false, - // Uniqueness is handled by base.rs, not attrunique here due to - // needing to check recycled objects too. - unique: false, - phantom: false, - index: vec![IndexType::Equality, IndexType::Presence], - syntax: SyntaxType::Uuid, - }, - ); - self.attributes.insert( - AttrString::from("last_modified_cid"), - SchemaAttribute { - name: AttrString::from("last_modified_cid"), - uuid: UUID_SCHEMA_ATTR_LAST_MOD_CID, - description: String::from("The cid of the last change to this object"), - multivalue: false, - // Uniqueness is handled by base.rs, not attrunique here due to - // needing to check recycled objects too. - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Cid, - }, - ); - self.attributes.insert( - AttrString::from("name"), - SchemaAttribute { - name: AttrString::from("name"), - uuid: UUID_SCHEMA_ATTR_NAME, - description: String::from("The shortform name of an object"), - multivalue: false, - unique: true, - phantom: false, - index: vec![IndexType::Equality, IndexType::Presence], - syntax: SyntaxType::Utf8StringIname, - }, - ); - self.attributes.insert( - AttrString::from("spn"), - SchemaAttribute { - name: AttrString::from("spn"), - uuid: UUID_SCHEMA_ATTR_SPN, - description: String::from( - "The Security Principal Name of an object, unique across all domain trusts", - ), - multivalue: false, - unique: true, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::SecurityPrincipalName, - }, - ); - self.attributes.insert( - AttrString::from("attributename"), - SchemaAttribute { - name: AttrString::from("attributename"), - uuid: UUID_SCHEMA_ATTR_ATTRIBUTENAME, - description: String::from("The name of a schema attribute"), - multivalue: false, - unique: true, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("classname"), - SchemaAttribute { - name: AttrString::from("classname"), - uuid: UUID_SCHEMA_ATTR_CLASSNAME, - description: String::from("The name of a schema class"), - multivalue: false, - unique: true, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("description"), - SchemaAttribute { - name: AttrString::from("description"), - uuid: UUID_SCHEMA_ATTR_DESCRIPTION, - description: String::from("A description of an attribute, object or class"), - multivalue: false, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8String, - }, - ); - self.attributes.insert(AttrString::from("multivalue"), SchemaAttribute { + // + self.classes.clear(); + self.attributes.clear(); + // Bootstrap in definitions of our own schema types + // First, add all the needed core attributes for schema parsing + self.attributes.insert( + AttrString::from("class"), + SchemaAttribute { + name: AttrString::from("class"), + uuid: UUID_SCHEMA_ATTR_CLASS, + description: String::from("The set of classes defining an object"), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality, IndexType::Presence], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("uuid"), + SchemaAttribute { + name: AttrString::from("uuid"), + uuid: UUID_SCHEMA_ATTR_UUID, + description: String::from("The universal unique id of the object"), + multivalue: false, + // Uniqueness is handled by base.rs, not attrunique here due to + // needing to check recycled objects too. + unique: false, + phantom: false, + index: vec![IndexType::Equality, IndexType::Presence], + syntax: SyntaxType::Uuid, + }, + ); + self.attributes.insert( + AttrString::from("last_modified_cid"), + SchemaAttribute { + name: AttrString::from("last_modified_cid"), + uuid: UUID_SCHEMA_ATTR_LAST_MOD_CID, + description: String::from("The cid of the last change to this object"), + multivalue: false, + // Uniqueness is handled by base.rs, not attrunique here due to + // needing to check recycled objects too. + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Cid, + }, + ); + self.attributes.insert( + AttrString::from("name"), + SchemaAttribute { + name: AttrString::from("name"), + uuid: UUID_SCHEMA_ATTR_NAME, + description: String::from("The shortform name of an object"), + multivalue: false, + unique: true, + phantom: false, + index: vec![IndexType::Equality, IndexType::Presence], + syntax: SyntaxType::Utf8StringIname, + }, + ); + self.attributes.insert( + AttrString::from("spn"), + SchemaAttribute { + name: AttrString::from("spn"), + uuid: UUID_SCHEMA_ATTR_SPN, + description: String::from( + "The Security Principal Name of an object, unique across all domain trusts", + ), + multivalue: false, + unique: true, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::SecurityPrincipalName, + }, + ); + self.attributes.insert( + AttrString::from("attributename"), + SchemaAttribute { + name: AttrString::from("attributename"), + uuid: UUID_SCHEMA_ATTR_ATTRIBUTENAME, + description: String::from("The name of a schema attribute"), + multivalue: false, + unique: true, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("classname"), + SchemaAttribute { + name: AttrString::from("classname"), + uuid: UUID_SCHEMA_ATTR_CLASSNAME, + description: String::from("The name of a schema class"), + multivalue: false, + unique: true, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("description"), + SchemaAttribute { + name: AttrString::from("description"), + uuid: UUID_SCHEMA_ATTR_DESCRIPTION, + description: String::from("A description of an attribute, object or class"), + multivalue: false, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8String, + }, + ); + self.attributes.insert(AttrString::from("multivalue"), SchemaAttribute { name: AttrString::from("multivalue"), uuid: UUID_SCHEMA_ATTR_MULTIVALUE, description: String::from("If true, this attribute is able to store multiple values rather than just a single value."), @@ -769,7 +769,7 @@ impl<'a> SchemaWriteTransaction<'a> { index: vec![], syntax: SyntaxType::Boolean, }); - self.attributes.insert(AttrString::from("phantom"), SchemaAttribute { + self.attributes.insert(AttrString::from("phantom"), SchemaAttribute { name: AttrString::from("phantom"), uuid: UUID_SCHEMA_ATTR_PHANTOM, description: String::from("If true, this attribute must NOT be present in any may/must sets of a class as. This represents generated attributes."), @@ -779,107 +779,112 @@ impl<'a> SchemaWriteTransaction<'a> { index: vec![], syntax: SyntaxType::Boolean, }); - self.attributes.insert(AttrString::from("unique"), SchemaAttribute { + self.attributes.insert( + AttrString::from("unique"), + SchemaAttribute { name: AttrString::from("unique"), uuid: UUID_SCHEMA_ATTR_UNIQUE, - description: String::from("If true, this attribute must store a unique value through out the database."), + description: String::from( + "If true, this attribute must store a unique value through out the database.", + ), multivalue: false, unique: false, phantom: false, index: vec![], syntax: SyntaxType::Boolean, - }); - self.attributes.insert( - AttrString::from("index"), - SchemaAttribute { - name: AttrString::from("index"), - uuid: UUID_SCHEMA_ATTR_INDEX, - description: String::from( - "Describe the indexes to apply to instances of this attribute.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::IndexId, - }, - ); - self.attributes.insert( - AttrString::from("syntax"), - SchemaAttribute { - name: AttrString::from("syntax"), - uuid: UUID_SCHEMA_ATTR_SYNTAX, - description: String::from( - "Describe the syntax of this attribute. This affects indexing and sorting.", - ), - multivalue: false, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::SyntaxId, - }, - ); - self.attributes.insert( - AttrString::from("systemmay"), - SchemaAttribute { - name: AttrString::from("systemmay"), - uuid: UUID_SCHEMA_ATTR_SYSTEMMAY, - description: String::from( - "A list of system provided optional attributes this class can store.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("may"), - SchemaAttribute { - name: AttrString::from("may"), - uuid: UUID_SCHEMA_ATTR_MAY, - description: String::from( - "A user modifiable list of optional attributes this class can store.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("systemmust"), - SchemaAttribute { - name: AttrString::from("systemmust"), - uuid: UUID_SCHEMA_ATTR_SYSTEMMUST, - description: String::from( - "A list of system provided required attributes this class must store.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("must"), - SchemaAttribute { - name: AttrString::from("must"), - uuid: UUID_SCHEMA_ATTR_MUST, - description: String::from( - "A user modifiable list of required attributes this class must store.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( + }, + ); + self.attributes.insert( + AttrString::from("index"), + SchemaAttribute { + name: AttrString::from("index"), + uuid: UUID_SCHEMA_ATTR_INDEX, + description: String::from( + "Describe the indexes to apply to instances of this attribute.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::IndexId, + }, + ); + self.attributes.insert( + AttrString::from("syntax"), + SchemaAttribute { + name: AttrString::from("syntax"), + uuid: UUID_SCHEMA_ATTR_SYNTAX, + description: String::from( + "Describe the syntax of this attribute. This affects indexing and sorting.", + ), + multivalue: false, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::SyntaxId, + }, + ); + self.attributes.insert( + AttrString::from("systemmay"), + SchemaAttribute { + name: AttrString::from("systemmay"), + uuid: UUID_SCHEMA_ATTR_SYSTEMMAY, + description: String::from( + "A list of system provided optional attributes this class can store.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("may"), + SchemaAttribute { + name: AttrString::from("may"), + uuid: UUID_SCHEMA_ATTR_MAY, + description: String::from( + "A user modifiable list of optional attributes this class can store.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("systemmust"), + SchemaAttribute { + name: AttrString::from("systemmust"), + uuid: UUID_SCHEMA_ATTR_SYSTEMMUST, + description: String::from( + "A list of system provided required attributes this class must store.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("must"), + SchemaAttribute { + name: AttrString::from("must"), + uuid: UUID_SCHEMA_ATTR_MUST, + description: String::from( + "A user modifiable list of required attributes this class must store.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( AttrString::from("systemsupplements"), SchemaAttribute { name: AttrString::from("systemsupplements"), @@ -894,7 +899,7 @@ impl<'a> SchemaWriteTransaction<'a> { syntax: SyntaxType::Utf8StringInsensitive, }, ); - self.attributes.insert( + self.attributes.insert( AttrString::from("supplements"), SchemaAttribute { name: AttrString::from("supplements"), @@ -909,22 +914,22 @@ impl<'a> SchemaWriteTransaction<'a> { syntax: SyntaxType::Utf8StringInsensitive, }, ); - self.attributes.insert( - AttrString::from("systemexcludes"), - SchemaAttribute { - name: AttrString::from("systemexcludes"), - uuid: UUID_SCHEMA_ATTR_SYSTEMEXCLUDES, - description: String::from( - "A set of classes that are denied presence in connection to this class", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( + self.attributes.insert( + AttrString::from("systemexcludes"), + SchemaAttribute { + name: AttrString::from("systemexcludes"), + uuid: UUID_SCHEMA_ATTR_SYSTEMEXCLUDES, + description: String::from( + "A set of classes that are denied presence in connection to this class", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( AttrString::from("excludes"), SchemaAttribute { name: AttrString::from("excludes"), @@ -940,9 +945,9 @@ impl<'a> SchemaWriteTransaction<'a> { }, ); - // SYSINFO attrs - // ACP attributes. - self.attributes.insert( + // SYSINFO attrs + // ACP attributes. + self.attributes.insert( AttrString::from("acp_enable"), SchemaAttribute { name: AttrString::from("acp_enable"), @@ -956,107 +961,111 @@ impl<'a> SchemaWriteTransaction<'a> { }, ); - self.attributes.insert( - AttrString::from("acp_receiver"), - SchemaAttribute { - name: AttrString::from("acp_receiver"), - uuid: UUID_SCHEMA_ATTR_ACP_RECEIVER, - description: String::from( - "Who the ACP applies to, constraining or allowing operations.", - ), - multivalue: false, - unique: false, - phantom: false, - index: vec![IndexType::Equality, IndexType::SubString], - syntax: SyntaxType::JsonFilter, - }, - ); - self.attributes.insert( - AttrString::from("acp_targetscope"), - SchemaAttribute { - name: AttrString::from("acp_targetscope"), - uuid: UUID_SCHEMA_ATTR_ACP_TARGETSCOPE, - description: String::from( - "The effective targets of the ACP, IE what will be acted upon.", - ), - multivalue: false, - unique: false, - phantom: false, - index: vec![IndexType::Equality, IndexType::SubString], - syntax: SyntaxType::JsonFilter, - }, - ); - self.attributes.insert( - AttrString::from("acp_search_attr"), - SchemaAttribute { - name: AttrString::from("acp_search_attr"), - uuid: UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR, - description: String::from("The attributes that may be viewed or searched by the reciever on targetscope."), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("acp_create_class"), - SchemaAttribute { - name: AttrString::from("acp_create_class"), - uuid: UUID_SCHEMA_ATTR_ACP_CREATE_CLASS, - description: String::from( - "The set of classes that can be created on a new entry.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("acp_create_attr"), - SchemaAttribute { - name: AttrString::from("acp_create_attr"), - uuid: UUID_SCHEMA_ATTR_ACP_CREATE_ATTR, - description: String::from( - "The set of attribute types that can be created on an entry.", - ), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); + self.attributes.insert( + AttrString::from("acp_receiver"), + SchemaAttribute { + name: AttrString::from("acp_receiver"), + uuid: UUID_SCHEMA_ATTR_ACP_RECEIVER, + description: String::from( + "Who the ACP applies to, constraining or allowing operations.", + ), + multivalue: false, + unique: false, + phantom: false, + index: vec![IndexType::Equality, IndexType::SubString], + syntax: SyntaxType::JsonFilter, + }, + ); + self.attributes.insert( + AttrString::from("acp_targetscope"), + SchemaAttribute { + name: AttrString::from("acp_targetscope"), + uuid: UUID_SCHEMA_ATTR_ACP_TARGETSCOPE, + description: String::from( + "The effective targets of the ACP, IE what will be acted upon.", + ), + multivalue: false, + unique: false, + phantom: false, + index: vec![IndexType::Equality, IndexType::SubString], + syntax: SyntaxType::JsonFilter, + }, + ); + self.attributes.insert( + AttrString::from("acp_search_attr"), + SchemaAttribute { + name: AttrString::from("acp_search_attr"), + uuid: UUID_SCHEMA_ATTR_ACP_SEARCH_ATTR, + description: String::from( + "The attributes that may be viewed or searched by the reciever on targetscope.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("acp_create_class"), + SchemaAttribute { + name: AttrString::from("acp_create_class"), + uuid: UUID_SCHEMA_ATTR_ACP_CREATE_CLASS, + description: String::from("The set of classes that can be created on a new entry."), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("acp_create_attr"), + SchemaAttribute { + name: AttrString::from("acp_create_attr"), + uuid: UUID_SCHEMA_ATTR_ACP_CREATE_ATTR, + description: String::from( + "The set of attribute types that can be created on an entry.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); - self.attributes.insert( - AttrString::from("acp_modify_removedattr"), - SchemaAttribute { - name: AttrString::from("acp_modify_removedattr"), - uuid: UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR, - description: String::from("The set of attribute types that could be removed or purged in a modification."), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("acp_modify_presentattr"), - SchemaAttribute { - name: AttrString::from("acp_modify_presentattr"), - uuid: UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR, - description: String::from("The set of attribute types that could be added or asserted in a modification."), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( + self.attributes.insert( + AttrString::from("acp_modify_removedattr"), + SchemaAttribute { + name: AttrString::from("acp_modify_removedattr"), + uuid: UUID_SCHEMA_ATTR_ACP_MODIFY_REMOVEDATTR, + description: String::from( + "The set of attribute types that could be removed or purged in a modification.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("acp_modify_presentattr"), + SchemaAttribute { + name: AttrString::from("acp_modify_presentattr"), + uuid: UUID_SCHEMA_ATTR_ACP_MODIFY_PRESENTATTR, + description: String::from( + "The set of attribute types that could be added or asserted in a modification.", + ), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( AttrString::from("acp_modify_class"), SchemaAttribute { name: AttrString::from("acp_modify_class"), @@ -1069,341 +1078,341 @@ impl<'a> SchemaWriteTransaction<'a> { syntax: SyntaxType::Utf8StringInsensitive, }, ); - // MO/Member - self.attributes.insert( - AttrString::from("memberof"), - SchemaAttribute { - name: AttrString::from("memberof"), - uuid: UUID_SCHEMA_ATTR_MEMBEROF, - description: String::from("reverse group membership of the object"), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::ReferenceUuid, - }, - ); - self.attributes.insert( - AttrString::from("directmemberof"), - SchemaAttribute { - name: AttrString::from("directmemberof"), - uuid: UUID_SCHEMA_ATTR_DIRECTMEMBEROF, - description: String::from("reverse direct group membership of the object"), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::ReferenceUuid, - }, - ); - self.attributes.insert( - AttrString::from("member"), - SchemaAttribute { - name: AttrString::from("member"), - uuid: UUID_SCHEMA_ATTR_MEMBER, - description: String::from("List of members of the group"), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::ReferenceUuid, - }, - ); - // Migration related - self.attributes.insert( - AttrString::from("version"), - SchemaAttribute { - name: AttrString::from("version"), - uuid: UUID_SCHEMA_ATTR_VERSION, - description: String::from( - "The systems internal migration version for provided objects", - ), - multivalue: false, - unique: false, - phantom: false, - index: vec![], - syntax: SyntaxType::Uint32, - }, - ); - // Domain for sysinfo - self.attributes.insert( - AttrString::from("domain"), - SchemaAttribute { - name: AttrString::from("domain"), - uuid: UUID_SCHEMA_ATTR_DOMAIN, - description: String::from("A DNS Domain name entry."), - multivalue: true, - unique: false, - phantom: false, - index: vec![IndexType::Equality], - syntax: SyntaxType::Utf8StringIname, - }, - ); - self.attributes.insert( - AttrString::from("claim"), - SchemaAttribute { - name: AttrString::from("claim"), - uuid: UUID_SCHEMA_ATTR_CLAIM, - description: String::from( - "The string identifier of an extracted claim that can be filtered", - ), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("scope"), - SchemaAttribute { - name: AttrString::from("scope"), - uuid: UUID_SCHEMA_ATTR_SCOPE, - description: String::from( - "The string identifier of a permission scope in a session", - ), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); + // MO/Member + self.attributes.insert( + AttrString::from("memberof"), + SchemaAttribute { + name: AttrString::from("memberof"), + uuid: UUID_SCHEMA_ATTR_MEMBEROF, + description: String::from("reverse group membership of the object"), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::ReferenceUuid, + }, + ); + self.attributes.insert( + AttrString::from("directmemberof"), + SchemaAttribute { + name: AttrString::from("directmemberof"), + uuid: UUID_SCHEMA_ATTR_DIRECTMEMBEROF, + description: String::from("reverse direct group membership of the object"), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::ReferenceUuid, + }, + ); + self.attributes.insert( + AttrString::from("member"), + SchemaAttribute { + name: AttrString::from("member"), + uuid: UUID_SCHEMA_ATTR_MEMBER, + description: String::from("List of members of the group"), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::ReferenceUuid, + }, + ); + // Migration related + self.attributes.insert( + AttrString::from("version"), + SchemaAttribute { + name: AttrString::from("version"), + uuid: UUID_SCHEMA_ATTR_VERSION, + description: String::from( + "The systems internal migration version for provided objects", + ), + multivalue: false, + unique: false, + phantom: false, + index: vec![], + syntax: SyntaxType::Uint32, + }, + ); + // Domain for sysinfo + self.attributes.insert( + AttrString::from("domain"), + SchemaAttribute { + name: AttrString::from("domain"), + uuid: UUID_SCHEMA_ATTR_DOMAIN, + description: String::from("A DNS Domain name entry."), + multivalue: true, + unique: false, + phantom: false, + index: vec![IndexType::Equality], + syntax: SyntaxType::Utf8StringIname, + }, + ); + self.attributes.insert( + AttrString::from("claim"), + SchemaAttribute { + name: AttrString::from("claim"), + uuid: UUID_SCHEMA_ATTR_CLAIM, + description: String::from( + "The string identifier of an extracted claim that can be filtered", + ), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("scope"), + SchemaAttribute { + name: AttrString::from("scope"), + uuid: UUID_SCHEMA_ATTR_SCOPE, + description: String::from( + "The string identifier of a permission scope in a session", + ), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); - self.attributes.insert( - AttrString::from("password_import"), - SchemaAttribute { - name: AttrString::from("password_import"), - uuid: UUID_SCHEMA_ATTR_PASSWORD_IMPORT, - description: String::from("An imported password hash from an external system."), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8String, - }, - ); + self.attributes.insert( + AttrString::from("password_import"), + SchemaAttribute { + name: AttrString::from("password_import"), + uuid: UUID_SCHEMA_ATTR_PASSWORD_IMPORT, + description: String::from("An imported password hash from an external system."), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8String, + }, + ); - // LDAP Masking Phantoms - self.attributes.insert( - AttrString::from("dn"), - SchemaAttribute { - name: AttrString::from("dn"), - uuid: UUID_SCHEMA_ATTR_DN, - description: String::from("An LDAP Compatible DN"), - multivalue: false, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("entrydn"), - SchemaAttribute { - name: AttrString::from("entrydn"), - uuid: UUID_SCHEMA_ATTR_ENTRYDN, - description: String::from("An LDAP Compatible EntryDN"), - multivalue: false, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("entryuuid"), - SchemaAttribute { - name: AttrString::from("entryuuid"), - uuid: UUID_SCHEMA_ATTR_ENTRYUUID, - description: String::from("An LDAP Compatible entryUUID"), - multivalue: false, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Uuid, - }, - ); - self.attributes.insert( - AttrString::from("objectclass"), - SchemaAttribute { - name: AttrString::from("objectclass"), - uuid: UUID_SCHEMA_ATTR_OBJECTCLASS, - description: String::from("An LDAP Compatible objectClass"), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringInsensitive, - }, - ); - self.attributes.insert( - AttrString::from("cn"), - SchemaAttribute { - name: AttrString::from("cn"), - uuid: UUID_SCHEMA_ATTR_CN, - description: String::from("An LDAP Compatible objectClass"), - multivalue: false, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Utf8StringIname, - }, - ); - self.attributes.insert( - AttrString::from("keys"), - SchemaAttribute { - name: AttrString::from("keys"), - uuid: UUID_SCHEMA_ATTR_KEYS, - description: String::from("An LDAP Compatible keys (ssh)"), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::SshKey, - }, - ); - self.attributes.insert( - AttrString::from("sshpublickey"), - SchemaAttribute { - name: AttrString::from("sshpublickey"), - uuid: UUID_SCHEMA_ATTR_SSHPUBLICKEY, - description: String::from("An LDAP Compatible sshPublicKey"), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::SshKey, - }, - ); - self.attributes.insert( - AttrString::from("email"), - SchemaAttribute { - name: AttrString::from("email"), - uuid: UUID_SCHEMA_ATTR_EMAIL, - description: String::from("An LDAP Compatible email"), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::EmailAddress, - }, - ); - self.attributes.insert( - AttrString::from("emailaddress"), - SchemaAttribute { - name: AttrString::from("emailaddress"), - uuid: UUID_SCHEMA_ATTR_EMAILADDRESS, - description: String::from("An LDAP Compatible emailAddress"), - multivalue: true, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::EmailAddress, - }, - ); - self.attributes.insert( - AttrString::from("uidnumber"), - SchemaAttribute { - name: AttrString::from("uidnumber"), - uuid: UUID_SCHEMA_ATTR_UIDNUMBER, - description: String::from("An LDAP Compatible uidNumber"), - multivalue: false, - unique: false, - phantom: true, - index: vec![], - syntax: SyntaxType::Uint32, - }, - ); - // end LDAP masking phantoms + // LDAP Masking Phantoms + self.attributes.insert( + AttrString::from("dn"), + SchemaAttribute { + name: AttrString::from("dn"), + uuid: UUID_SCHEMA_ATTR_DN, + description: String::from("An LDAP Compatible DN"), + multivalue: false, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("entrydn"), + SchemaAttribute { + name: AttrString::from("entrydn"), + uuid: UUID_SCHEMA_ATTR_ENTRYDN, + description: String::from("An LDAP Compatible EntryDN"), + multivalue: false, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("entryuuid"), + SchemaAttribute { + name: AttrString::from("entryuuid"), + uuid: UUID_SCHEMA_ATTR_ENTRYUUID, + description: String::from("An LDAP Compatible entryUUID"), + multivalue: false, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Uuid, + }, + ); + self.attributes.insert( + AttrString::from("objectclass"), + SchemaAttribute { + name: AttrString::from("objectclass"), + uuid: UUID_SCHEMA_ATTR_OBJECTCLASS, + description: String::from("An LDAP Compatible objectClass"), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringInsensitive, + }, + ); + self.attributes.insert( + AttrString::from("cn"), + SchemaAttribute { + name: AttrString::from("cn"), + uuid: UUID_SCHEMA_ATTR_CN, + description: String::from("An LDAP Compatible objectClass"), + multivalue: false, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Utf8StringIname, + }, + ); + self.attributes.insert( + AttrString::from("keys"), + SchemaAttribute { + name: AttrString::from("keys"), + uuid: UUID_SCHEMA_ATTR_KEYS, + description: String::from("An LDAP Compatible keys (ssh)"), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::SshKey, + }, + ); + self.attributes.insert( + AttrString::from("sshpublickey"), + SchemaAttribute { + name: AttrString::from("sshpublickey"), + uuid: UUID_SCHEMA_ATTR_SSHPUBLICKEY, + description: String::from("An LDAP Compatible sshPublicKey"), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::SshKey, + }, + ); + self.attributes.insert( + AttrString::from("email"), + SchemaAttribute { + name: AttrString::from("email"), + uuid: UUID_SCHEMA_ATTR_EMAIL, + description: String::from("An LDAP Compatible email"), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::EmailAddress, + }, + ); + self.attributes.insert( + AttrString::from("emailaddress"), + SchemaAttribute { + name: AttrString::from("emailaddress"), + uuid: UUID_SCHEMA_ATTR_EMAILADDRESS, + description: String::from("An LDAP Compatible emailAddress"), + multivalue: true, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::EmailAddress, + }, + ); + self.attributes.insert( + AttrString::from("uidnumber"), + SchemaAttribute { + name: AttrString::from("uidnumber"), + uuid: UUID_SCHEMA_ATTR_UIDNUMBER, + description: String::from("An LDAP Compatible uidNumber"), + multivalue: false, + unique: false, + phantom: true, + index: vec![], + syntax: SyntaxType::Uint32, + }, + ); + // end LDAP masking phantoms - self.classes.insert( - AttrString::from("attributetype"), - SchemaClass { - name: AttrString::from("attributetype"), - uuid: UUID_SCHEMA_CLASS_ATTRIBUTETYPE, - description: String::from("Definition of a schema attribute"), - systemmay: vec![AttrString::from("phantom"), AttrString::from("index")], - systemmust: vec![ - AttrString::from("class"), - AttrString::from("attributename"), - AttrString::from("multivalue"), - AttrString::from("unique"), - AttrString::from("syntax"), - AttrString::from("description"), - ], - systemexcludes: vec![AttrString::from("classtype")], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("classtype"), - SchemaClass { - name: AttrString::from("classtype"), - uuid: UUID_SCHEMA_CLASS_CLASSTYPE, - description: String::from("Definition of a schema classtype"), - systemmay: vec![ - AttrString::from("systemmay"), - AttrString::from("may"), - AttrString::from("systemmust"), - AttrString::from("must"), - AttrString::from("systemsupplements"), - AttrString::from("supplements"), - AttrString::from("systemexcludes"), - AttrString::from("excludes"), - ], - systemmust: vec![ - AttrString::from("class"), - AttrString::from("classname"), - AttrString::from("description"), - ], - systemexcludes: vec![AttrString::from("attributetype")], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("object"), - SchemaClass { - name: AttrString::from("object"), - uuid: UUID_SCHEMA_CLASS_OBJECT, - description: String::from( - "A system created class that all objects must contain", - ), - systemmay: vec![AttrString::from("description")], - systemmust: vec![ - AttrString::from("class"), - AttrString::from("uuid"), - AttrString::from("last_modified_cid"), - ], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("memberof"), - SchemaClass { - name: AttrString::from("memberof"), - uuid: UUID_SCHEMA_CLASS_MEMBEROF, - description: String::from("Class that is dynamically added to recepients of memberof or directmemberof"), - systemmay: vec![ - AttrString::from("memberof"), - AttrString::from("directmemberof") - ], - .. Default::default() - }, - ); - self.classes.insert( - AttrString::from("extensibleobject"), - SchemaClass { - name: AttrString::from("extensibleobject"), - uuid: UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT, - description: String::from( - "A class type that has green hair and turns off all rules ...", - ), - ..Default::default() - }, - ); - /* These two classes are core to the entry lifecycle for recycling and tombstoning */ - self.classes.insert( + self.classes.insert( + AttrString::from("attributetype"), + SchemaClass { + name: AttrString::from("attributetype"), + uuid: UUID_SCHEMA_CLASS_ATTRIBUTETYPE, + description: String::from("Definition of a schema attribute"), + systemmay: vec![AttrString::from("phantom"), AttrString::from("index")], + systemmust: vec![ + AttrString::from("class"), + AttrString::from("attributename"), + AttrString::from("multivalue"), + AttrString::from("unique"), + AttrString::from("syntax"), + AttrString::from("description"), + ], + systemexcludes: vec![AttrString::from("classtype")], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("classtype"), + SchemaClass { + name: AttrString::from("classtype"), + uuid: UUID_SCHEMA_CLASS_CLASSTYPE, + description: String::from("Definition of a schema classtype"), + systemmay: vec![ + AttrString::from("systemmay"), + AttrString::from("may"), + AttrString::from("systemmust"), + AttrString::from("must"), + AttrString::from("systemsupplements"), + AttrString::from("supplements"), + AttrString::from("systemexcludes"), + AttrString::from("excludes"), + ], + systemmust: vec![ + AttrString::from("class"), + AttrString::from("classname"), + AttrString::from("description"), + ], + systemexcludes: vec![AttrString::from("attributetype")], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("object"), + SchemaClass { + name: AttrString::from("object"), + uuid: UUID_SCHEMA_CLASS_OBJECT, + description: String::from("A system created class that all objects must contain"), + systemmay: vec![AttrString::from("description")], + systemmust: vec![ + AttrString::from("class"), + AttrString::from("uuid"), + AttrString::from("last_modified_cid"), + ], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("memberof"), + SchemaClass { + name: AttrString::from("memberof"), + uuid: UUID_SCHEMA_CLASS_MEMBEROF, + description: String::from( + "Class that is dynamically added to recepients of memberof or directmemberof", + ), + systemmay: vec![ + AttrString::from("memberof"), + AttrString::from("directmemberof"), + ], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("extensibleobject"), + SchemaClass { + name: AttrString::from("extensibleobject"), + uuid: UUID_SCHEMA_CLASS_EXTENSIBLEOBJECT, + description: String::from( + "A class type that has green hair and turns off all rules ...", + ), + ..Default::default() + }, + ); + /* These two classes are core to the entry lifecycle for recycling and tombstoning */ + self.classes.insert( AttrString::from("recycled"), SchemaClass { name: AttrString::from("recycled"), @@ -1412,7 +1421,7 @@ impl<'a> SchemaWriteTransaction<'a> { .. Default::default() }, ); - self.classes.insert( + self.classes.insert( AttrString::from("tombstone"), SchemaClass { name: AttrString::from("tombstone"), @@ -1425,89 +1434,89 @@ impl<'a> SchemaWriteTransaction<'a> { .. Default::default() }, ); - // sysinfo - self.classes.insert( - AttrString::from("system_info"), - SchemaClass { - name: AttrString::from("system_info"), - uuid: UUID_SCHEMA_CLASS_SYSTEM_INFO, - description: String::from("System metadata object class"), - systemmust: vec![AttrString::from("version")], - ..Default::default() - }, - ); - // ACP - self.classes.insert( - AttrString::from("access_control_profile"), - SchemaClass { - name: AttrString::from("access_control_profile"), - uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE, - description: String::from("System Access Control Profile Class"), - systemmay: vec![ - AttrString::from("acp_enable"), - AttrString::from("description"), - ], - systemmust: vec![ - AttrString::from("acp_receiver"), - AttrString::from("acp_targetscope"), - AttrString::from("name"), - ], - systemsupplements: vec![ - AttrString::from("access_control_search"), - AttrString::from("access_control_delete"), - AttrString::from("access_control_modify"), - AttrString::from("access_control_create"), - ], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("access_control_search"), - SchemaClass { - name: AttrString::from("access_control_search"), - uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH, - description: String::from("System Access Control Search Class"), - systemmust: vec![AttrString::from("acp_search_attr")], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("access_control_delete"), - SchemaClass { - name: AttrString::from("access_control_delete"), - uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE, - description: String::from("System Access Control DELETE Class"), - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("access_control_modify"), - SchemaClass { - name: AttrString::from("access_control_modify"), - uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY, - description: String::from("System Access Control Modify Class"), - systemmay: vec![ - AttrString::from("acp_modify_removedattr"), - AttrString::from("acp_modify_presentattr"), - AttrString::from("acp_modify_class"), - ], - ..Default::default() - }, - ); - self.classes.insert( - AttrString::from("access_control_create"), - SchemaClass { - name: AttrString::from("access_control_create"), - uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE, - description: String::from("System Access Control Create Class"), - systemmay: vec![ - AttrString::from("acp_create_class"), - AttrString::from("acp_create_attr"), - ], - ..Default::default() - }, - ); - self.classes.insert( + // sysinfo + self.classes.insert( + AttrString::from("system_info"), + SchemaClass { + name: AttrString::from("system_info"), + uuid: UUID_SCHEMA_CLASS_SYSTEM_INFO, + description: String::from("System metadata object class"), + systemmust: vec![AttrString::from("version")], + ..Default::default() + }, + ); + // ACP + self.classes.insert( + AttrString::from("access_control_profile"), + SchemaClass { + name: AttrString::from("access_control_profile"), + uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_PROFILE, + description: String::from("System Access Control Profile Class"), + systemmay: vec![ + AttrString::from("acp_enable"), + AttrString::from("description"), + ], + systemmust: vec![ + AttrString::from("acp_receiver"), + AttrString::from("acp_targetscope"), + AttrString::from("name"), + ], + systemsupplements: vec![ + AttrString::from("access_control_search"), + AttrString::from("access_control_delete"), + AttrString::from("access_control_modify"), + AttrString::from("access_control_create"), + ], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("access_control_search"), + SchemaClass { + name: AttrString::from("access_control_search"), + uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_SEARCH, + description: String::from("System Access Control Search Class"), + systemmust: vec![AttrString::from("acp_search_attr")], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("access_control_delete"), + SchemaClass { + name: AttrString::from("access_control_delete"), + uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_DELETE, + description: String::from("System Access Control DELETE Class"), + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("access_control_modify"), + SchemaClass { + name: AttrString::from("access_control_modify"), + uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_MODIFY, + description: String::from("System Access Control Modify Class"), + systemmay: vec![ + AttrString::from("acp_modify_removedattr"), + AttrString::from("acp_modify_presentattr"), + AttrString::from("acp_modify_class"), + ], + ..Default::default() + }, + ); + self.classes.insert( + AttrString::from("access_control_create"), + SchemaClass { + name: AttrString::from("access_control_create"), + uuid: UUID_SCHEMA_CLASS_ACCESS_CONTROL_CREATE, + description: String::from("System Access Control Create Class"), + systemmay: vec![ + AttrString::from("acp_create_class"), + AttrString::from("acp_create_attr"), + ], + ..Default::default() + }, + ); + self.classes.insert( AttrString::from("system"), SchemaClass { name: AttrString::from("system"), @@ -1517,15 +1526,14 @@ impl<'a> SchemaWriteTransaction<'a> { }, ); - let r = self.validate(); - if r.is_empty() { - admin_debug!("schema validate -> passed"); - Ok(()) - } else { - admin_error!(err = ?r, "schema validate -> errors"); - Err(OperationError::ConsistencyError(r)) - } - }) + let r = self.validate(); + if r.is_empty() { + admin_debug!("schema validate -> passed"); + Ok(()) + } else { + admin_error!(err = ?r, "schema validate -> errors"); + Err(OperationError::ConsistencyError(r)) + } } } @@ -1624,12 +1632,14 @@ impl Schema { #[cfg(test)] mod tests { - use crate::prelude::*; - use crate::schema::SchemaTransaction; - use crate::schema::{IndexType, Schema, SchemaAttribute, SchemaClass, SyntaxType}; use kanidm_proto::v1::{ConsistencyError, SchemaError}; use uuid::Uuid; + use crate::prelude::*; + use crate::schema::{ + IndexType, Schema, SchemaAttribute, SchemaClass, SchemaTransaction, SyntaxType, + }; + // use crate::proto_v1::Filter as ProtoFilter; macro_rules! validate_schema { diff --git a/kanidmd/idm/src/server.rs b/kanidmd/idm/src/server.rs index c13c34aa2..5c69bbe6f 100644 --- a/kanidmd/idm/src/server.rs +++ b/kanidmd/idm/src/server.rs @@ -3,13 +3,15 @@ // This is really only used for long lived, high level types that need clone // that otherwise can't be cloned. Think Mutex. +use std::cell::Cell; +use std::sync::Arc; +use std::time::Duration; + use async_std::task; use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn}; use concread::cowcell::*; use hashbrown::{HashMap, HashSet}; -use std::cell::Cell; -use std::sync::Arc; -use std::time::Duration; +use kanidm_proto::v1::{ConsistencyError, SchemaError}; use tokio::sync::{Semaphore, SemaphorePermit}; use tracing::trace; @@ -19,7 +21,6 @@ use crate::access::{ AccessControlsWriteTransaction, }; use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction}; -use crate::prelude::*; // We use so many, we just import them all ... use crate::event::{ CreateEvent, DeleteEvent, ExistsEvent, ModifyEvent, ReviveRecycledEvent, SearchEvent, @@ -29,13 +30,13 @@ use crate::identity::IdentityId; use crate::modify::{Modify, ModifyInvalid, ModifyList, ModifyValid}; use crate::plugins::dyngroup::{DynGroup, DynGroupCache}; use crate::plugins::Plugins; +use crate::prelude::*; use crate::repl::cid::Cid; use crate::schema::{ Schema, SchemaAttribute, SchemaClass, SchemaReadTransaction, SchemaTransaction, SchemaWriteTransaction, }; use crate::valueset::uuid_to_proto_string; -use kanidm_proto::v1::{ConsistencyError, SchemaError}; const RESOLVE_FILTER_CACHE_MAX: usize = 4096; const RESOLVE_FILTER_CACHE_LOCAL: usize = 0; @@ -177,107 +178,103 @@ pub trait QueryServerTransaction<'a> { /// [`SearchEvent`]: ../event/struct.SearchEvent.html /// [`access`]: ../access/index.html /// [`fn search`]: trait.QueryServerTransaction.html#method.search + #[instrument(level = "debug", skip_all)] fn search_ext( &self, se: &SearchEvent, ) -> Result>, OperationError> { - spanned!("server::search_ext", { - /* - * This just wraps search, but it's for the external interface - * so as a result it also reduces the entry set's attributes at - * the end. - */ - let entries = self.search(se)?; + /* + * This just wraps search, but it's for the external interface + * so as a result it also reduces the entry set's attributes at + * the end. + */ + let entries = self.search(se)?; - let access = self.get_accesscontrols(); - access - .search_filter_entry_attributes(se, entries) - .map_err(|e| { - // Log and fail if something went wrong. - admin_error!(?e, "Failed to filter entry attributes"); - e - }) - // This now returns the reduced vec. - }) + let access = self.get_accesscontrols(); + access + .search_filter_entry_attributes(se, entries) + .map_err(|e| { + // Log and fail if something went wrong. + admin_error!(?e, "Failed to filter entry attributes"); + e + }) + // This now returns the reduced vec. } + #[instrument(level = "debug", skip_all)] fn search(&self, se: &SearchEvent) -> Result>, OperationError> { - spanned!("server::search", { - if se.ident.is_internal() { - trace!(internal_filter = ?se.filter, "search"); - } else { - security_info!(initiator = %se.ident, "search"); - admin_info!(external_filter = ?se.filter, "search"); - } + if se.ident.is_internal() { + trace!(internal_filter = ?se.filter, "search"); + } else { + security_info!(initiator = %se.ident, "search"); + admin_info!(external_filter = ?se.filter, "search"); + } - // This is an important security step because it prevents us from - // performing un-indexed searches on attr's that don't exist in the - // server. This is why ExtensibleObject can only take schema that - // exists in the server, not arbitrary attr names. - // - // This normalises and validates in a single step. - // - // NOTE: Filters are validated in event conversion. + // This is an important security step because it prevents us from + // performing un-indexed searches on attr's that don't exist in the + // server. This is why ExtensibleObject can only take schema that + // exists in the server, not arbitrary attr names. + // + // This normalises and validates in a single step. + // + // NOTE: Filters are validated in event conversion. - let resolve_filter_cache = self.get_resolve_filter_cache(); + let resolve_filter_cache = self.get_resolve_filter_cache(); - let be_txn = self.get_be_txn(); - let idxmeta = be_txn.get_idxmeta_ref(); - // Now resolve all references and indexes. - let vfr = spanned!("server::search", { - se.filter - .resolve(&se.ident, Some(idxmeta), Some(resolve_filter_cache)) - }) + let be_txn = self.get_be_txn(); + let idxmeta = be_txn.get_idxmeta_ref(); + // Now resolve all references and indexes. + let vfr = se + .filter + .resolve(&se.ident, Some(idxmeta), Some(resolve_filter_cache)) .map_err(|e| { admin_error!(?e, "search filter resolve failure"); e })?; - let lims = se.get_limits(); + let lims = se.get_limits(); - // NOTE: We currently can't build search plugins due to the inability to hand - // the QS wr/ro to the plugin trait. However, there shouldn't be a need for search - // plugins, because all data transforms should be in the write path. + // NOTE: We currently can't build search plugins due to the inability to hand + // the QS wr/ro to the plugin trait. However, there shouldn't be a need for search + // plugins, because all data transforms should be in the write path. - let res = self.get_be_txn().search(lims, &vfr).map_err(|e| { - admin_error!(?e, "backend failure"); - OperationError::Backend - })?; + let res = self.get_be_txn().search(lims, &vfr).map_err(|e| { + admin_error!(?e, "backend failure"); + OperationError::Backend + })?; - // Apply ACP before we let the plugins "have at it". - // WARNING; for external searches this is NOT the only - // ACP application. There is a second application to reduce the - // attribute set on the entries! - // - let access = self.get_accesscontrols(); - access.search_filter_entries(se, res).map_err(|e| { - admin_error!(?e, "Unable to access filter entries"); - e - }) + // Apply ACP before we let the plugins "have at it". + // WARNING; for external searches this is NOT the only + // ACP application. There is a second application to reduce the + // attribute set on the entries! + // + let access = self.get_accesscontrols(); + access.search_filter_entries(se, res).map_err(|e| { + admin_error!(?e, "Unable to access filter entries"); + e }) } + #[instrument(level = "debug", skip_all)] fn exists(&self, ee: &ExistsEvent) -> Result { - spanned!("server::exists", { - let be_txn = self.get_be_txn(); - let idxmeta = be_txn.get_idxmeta_ref(); + let be_txn = self.get_be_txn(); + let idxmeta = be_txn.get_idxmeta_ref(); - let resolve_filter_cache = self.get_resolve_filter_cache(); + let resolve_filter_cache = self.get_resolve_filter_cache(); - let vfr = ee - .filter - .resolve(&ee.ident, Some(idxmeta), Some(resolve_filter_cache)) - .map_err(|e| { - admin_error!(?e, "Failed to resolve filter"); - e - })?; + let vfr = ee + .filter + .resolve(&ee.ident, Some(idxmeta), Some(resolve_filter_cache)) + .map_err(|e| { + admin_error!(?e, "Failed to resolve filter"); + e + })?; - let lims = ee.get_limits(); + let lims = ee.get_limits(); - self.get_be_txn().exists(lims, &vfr).map_err(|e| { - admin_error!(?e, "backend failure"); - OperationError::Backend - }) + self.get_be_txn().exists(lims, &vfr).map_err(|e| { + admin_error!(?e, "backend failure"); + OperationError::Backend }) } @@ -327,42 +324,39 @@ pub trait QueryServerTransaction<'a> { } /// From internal, generate an "exists" event and dispatch + #[instrument(level = "debug", skip_all)] fn internal_exists(&self, filter: Filter) -> Result { - spanned!("server::internal_exists", { - // Check the filter - let f_valid = filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - // Build an exists event - let ee = ExistsEvent::new_internal(f_valid); - // Submit it - self.exists(&ee) - }) + // Check the filter + let f_valid = filter + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + // Build an exists event + let ee = ExistsEvent::new_internal(f_valid); + // Submit it + self.exists(&ee) } + #[instrument(level = "debug", skip_all)] fn internal_search( &self, filter: Filter, ) -> Result>, OperationError> { - spanned!("server::internal_search", { - let f_valid = filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - let se = SearchEvent::new_internal(f_valid); - self.search(&se) - }) + let f_valid = filter + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + let se = SearchEvent::new_internal(f_valid); + self.search(&se) } + #[instrument(level = "debug", skip_all)] fn impersonate_search_valid( &self, f_valid: Filter, f_intent_valid: Filter, event: &Identity, ) -> Result>, OperationError> { - spanned!("server::internal_search_valid", { - let se = SearchEvent::new_impersonate(event, f_valid, f_intent_valid); - self.search(&se) - }) + let se = SearchEvent::new_impersonate(event, f_valid, f_intent_valid); + self.search(&se) } /// Applies ACP to filter result entries. @@ -392,78 +386,73 @@ pub trait QueryServerTransaction<'a> { self.impersonate_search_valid(f_valid, f_intent_valid, event) } + #[instrument(level = "debug", skip_all)] fn impersonate_search_ext( &self, filter: Filter, filter_intent: Filter, event: &Identity, ) -> Result>, OperationError> { - spanned!("server::internal_search_ext_valid", { - let f_valid = filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - let f_intent_valid = filter_intent - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - self.impersonate_search_ext_valid(f_valid, f_intent_valid, event) - }) + let f_valid = filter + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + let f_intent_valid = filter_intent + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + self.impersonate_search_ext_valid(f_valid, f_intent_valid, event) } /// Get a single entry by its UUID. This is used heavily for internal /// server operations, especially in login and ACP checks. + #[instrument(level = "debug", skip_all)] fn internal_search_uuid( &self, uuid: &Uuid, ) -> Result, OperationError> { - spanned!("server::internal_search_uuid", { - let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); - let f_valid = spanned!("server::internal_search_uuid", { - filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation) // I feel like we should log this... - })?; - let se = SearchEvent::new_internal(f_valid); + let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); + let f_valid = filter.validate(self.get_schema()).map_err(|e| { + error!(?e, "Filter Validate - SchemaViolation"); + OperationError::SchemaViolation(e) + })?; + let se = SearchEvent::new_internal(f_valid); - let mut vs = self.search(&se)?; - match vs.pop() { - Some(entry) if vs.is_empty() => Ok(entry), - _ => Err(OperationError::NoMatchingEntries), - } - }) + let mut vs = self.search(&se)?; + match vs.pop() { + Some(entry) if vs.is_empty() => Ok(entry), + _ => Err(OperationError::NoMatchingEntries), + } } + #[instrument(level = "debug", skip_all)] fn impersonate_search_ext_uuid( &self, uuid: &Uuid, event: &Identity, ) -> Result, OperationError> { - spanned!("server::internal_search_ext_uuid", { - let filter_intent = filter_all!(f_eq("uuid", PartialValue::new_uuid(*uuid))); - let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); + let filter_intent = filter_all!(f_eq("uuid", PartialValue::new_uuid(*uuid))); + let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); - let mut vs = self.impersonate_search_ext(filter, filter_intent, event)?; - match vs.pop() { - Some(entry) if vs.is_empty() => Ok(entry), - _ => Err(OperationError::NoMatchingEntries), - } - }) + let mut vs = self.impersonate_search_ext(filter, filter_intent, event)?; + match vs.pop() { + Some(entry) if vs.is_empty() => Ok(entry), + _ => Err(OperationError::NoMatchingEntries), + } } + #[instrument(level = "debug", skip_all)] fn impersonate_search_uuid( &self, uuid: &Uuid, event: &Identity, ) -> Result, OperationError> { - spanned!("server::internal_search_uuid", { - let filter_intent = filter_all!(f_eq("uuid", PartialValue::new_uuid(*uuid))); - let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); + let filter_intent = filter_all!(f_eq("uuid", PartialValue::new_uuid(*uuid))); + let filter = filter!(f_eq("uuid", PartialValue::new_uuid(*uuid))); - let mut vs = self.impersonate_search(filter, filter_intent, event)?; - match vs.pop() { - Some(entry) if vs.is_empty() => Ok(entry), - _ => Err(OperationError::NoMatchingEntries), - } - }) + let mut vs = self.impersonate_search(filter, filter_intent, event)?; + match vs.pop() { + Some(entry) if vs.is_empty() => Ok(entry), + _ => Err(OperationError::NoMatchingEntries), + } } /// Do a schema aware conversion from a String:String to String:Value for modification @@ -807,20 +796,18 @@ pub trait QueryServerTransaction<'a> { // This is the core of the server, as it processes the entire event // applies all parts required in order and more. impl<'a> QueryServerTransaction<'a> for QueryServerReadTransaction<'a> { + type AccessControlsTransactionType = AccessControlsReadTransaction<'a>; type BackendTransactionType = BackendReadTransaction<'a>; + type SchemaTransactionType = SchemaReadTransaction; fn get_be_txn(&self) -> &BackendReadTransaction<'a> { &self.be_txn } - type SchemaTransactionType = SchemaReadTransaction; - fn get_schema(&self) -> &SchemaReadTransaction { &self.schema } - type AccessControlsTransactionType = AccessControlsReadTransaction<'a>; - fn get_accesscontrols(&self) -> &AccessControlsReadTransaction<'a> { &self.accesscontrols } @@ -890,20 +877,18 @@ impl<'a> QueryServerReadTransaction<'a> { // the entry changelogs are consistent to their entries. let schema = self.get_schema(); - spanned!("server::verify", { - let filt_all = filter!(f_pres("class")); - let all_entries = match self.internal_search(filt_all) { - Ok(a) => a, - Err(_e) => return vec![Err(ConsistencyError::QueryServerSearchFailure)], - }; + let filt_all = filter!(f_pres("class")); + let all_entries = match self.internal_search(filt_all) { + Ok(a) => a, + Err(_e) => return vec![Err(ConsistencyError::QueryServerSearchFailure)], + }; - for e in all_entries { - e.verify(schema, &mut results) - } + for e in all_entries { + e.verify(schema, &mut results) + } - // Verify the RUV to the entry changelogs now. - self.get_be_txn().verify_ruv(&mut results); - }); + // Verify the RUV to the entry changelogs now. + self.get_be_txn().verify_ruv(&mut results); // Ok entries passed, lets move on to the content. // Most of our checks are in the plugins, so we let them @@ -918,20 +903,18 @@ impl<'a> QueryServerReadTransaction<'a> { } impl<'a> QueryServerTransaction<'a> for QueryServerWriteTransaction<'a> { + type AccessControlsTransactionType = AccessControlsWriteTransaction<'a>; type BackendTransactionType = BackendWriteTransaction<'a>; + type SchemaTransactionType = SchemaWriteTransaction<'a>; fn get_be_txn(&self) -> &BackendWriteTransaction<'a> { &self.be_txn } - type SchemaTransactionType = SchemaWriteTransaction<'a>; - fn get_schema(&self) -> &SchemaWriteTransaction<'a> { &self.schema } - type AccessControlsTransactionType = AccessControlsWriteTransaction<'a>; - fn get_accesscontrols(&self) -> &AccessControlsWriteTransaction<'a> { &self.accesscontrols } @@ -1221,859 +1204,827 @@ impl QueryServer { } impl<'a> QueryServerWriteTransaction<'a> { + #[instrument(level = "debug", skip_all)] pub fn create(&self, ce: &CreateEvent) -> Result<(), OperationError> { - spanned!("server::create", { - // The create event is a raw, read only representation of the request - // that was made to us, including information about the identity - // performing the request. - if !ce.ident.is_internal() { - security_info!(name = %ce.ident, "create initiator"); - } + // The create event is a raw, read only representation of the request + // that was made to us, including information about the identity + // performing the request. + if !ce.ident.is_internal() { + security_info!(name = %ce.ident, "create initiator"); + } - // Log the request + // Log the request - // TODO #67: Do we need limits on number of creates, or do we constraint - // based on request size in the frontend? + // TODO #67: Do we need limits on number of creates, or do we constraint + // based on request size in the frontend? - // Copy the entries to a writeable form, this involves assigning a - // change id so we can track what's happening. - let candidates: Vec> = ce.entries.clone(); + // Copy the entries to a writeable form, this involves assigning a + // change id so we can track what's happening. + let candidates: Vec> = ce.entries.clone(); - // Do we have rights to perform these creates? - // create_allow_operation - let access = self.get_accesscontrols(); - let op_allow = access - .create_allow_operation(ce, &candidates) - .map_err(|e| { - admin_error!("Failed to check create access {:?}", e); - e - })?; - if !op_allow { - return Err(OperationError::AccessDenied); - } - - // Before we assign replication metadata, we need to assert these entries - // are valid to create within the set of replication transitions. This - // means they *can not* be recycled or tombstones! - if candidates.iter().any(|e| e.mask_recycled_ts().is_none()) { - admin_warn!("Refusing to create invalid entries that are attempting to bypass replication state machine."); - return Err(OperationError::AccessDenied); - } - - // Assign our replication metadata now, since we can proceed with this operation. - let mut candidates: Vec> = candidates - .into_iter() - .map(|e| e.assign_cid(self.cid.clone(), &self.schema)) - .collect(); - - // run any pre plugins, giving them the list of mutable candidates. - // pre-plugins are defined here in their correct order of calling! - // I have no intent to make these dynamic or configurable. - - Plugins::run_pre_create_transform(self, &mut candidates, ce).map_err(|e| { - admin_error!("Create operation failed (pre_transform plugin), {:?}", e); + // Do we have rights to perform these creates? + // create_allow_operation + let access = self.get_accesscontrols(); + let op_allow = access + .create_allow_operation(ce, &candidates) + .map_err(|e| { + admin_error!("Failed to check create access {:?}", e); e })?; + if !op_allow { + return Err(OperationError::AccessDenied); + } - // NOTE: This is how you map from Vec> to Result> - // remember, that you only get the first error and the iter terminates. + // Before we assign replication metadata, we need to assert these entries + // are valid to create within the set of replication transitions. This + // means they *can not* be recycled or tombstones! + if candidates.iter().any(|e| e.mask_recycled_ts().is_none()) { + admin_warn!("Refusing to create invalid entries that are attempting to bypass replication state machine."); + return Err(OperationError::AccessDenied); + } - // eprintln!("{:?}", candidates); + // Assign our replication metadata now, since we can proceed with this operation. + let mut candidates: Vec> = candidates + .into_iter() + .map(|e| e.assign_cid(self.cid.clone(), &self.schema)) + .collect(); - // Now, normalise AND validate! + // run any pre plugins, giving them the list of mutable candidates. + // pre-plugins are defined here in their correct order of calling! + // I have no intent to make these dynamic or configurable. - let res: Result>, OperationError> = candidates - .into_iter() - .map(|e| { - e.validate(&self.schema) - .map_err(|e| { - admin_error!("Schema Violation in create validate {:?}", e); - OperationError::SchemaViolation(e) - }) - .map(|e| { - // Then seal the changes? - e.seal(&self.schema) - }) - }) - .collect(); + Plugins::run_pre_create_transform(self, &mut candidates, ce).map_err(|e| { + admin_error!("Create operation failed (pre_transform plugin), {:?}", e); + e + })?; - let norm_cand: Vec> = res?; + // NOTE: This is how you map from Vec> to Result> + // remember, that you only get the first error and the iter terminates. - // Run any pre-create plugins now with schema validated entries. - // This is important for normalisation of certain types IE class - // or attributes for these checks. - Plugins::run_pre_create(self, &norm_cand, ce).map_err(|e| { - admin_error!("Create operation failed (plugin), {:?}", e); - e - })?; + // eprintln!("{:?}", candidates); - // We may change from ce.entries later to something else? - let commit_cand = self.be_txn.create(&self.cid, norm_cand).map_err(|e| { - admin_error!("betxn create failure {:?}", e); - e - })?; + // Now, normalise AND validate! - // Run any post plugins + let res: Result>, OperationError> = candidates + .into_iter() + .map(|e| { + e.validate(&self.schema) + .map_err(|e| { + admin_error!("Schema Violation in create validate {:?}", e); + OperationError::SchemaViolation(e) + }) + .map(|e| { + // Then seal the changes? + e.seal(&self.schema) + }) + }) + .collect(); - Plugins::run_post_create(self, &commit_cand, ce).map_err(|e| { - admin_error!("Create operation failed (post plugin), {:?}", e); - e - })?; + let norm_cand: Vec> = res?; - // We have finished all plugs and now have a successful operation - flag if - // schema or acp requires reload. - if !self.changed_schema.get() { - self.changed_schema.set(commit_cand.iter().any(|e| { - e.attribute_equality("class", &PVCLASS_CLASSTYPE) - || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) - })) - } - if !self.changed_acp.get() { - self.changed_acp.set( - commit_cand - .iter() - .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), - ) - } - if !self.changed_oauth2.get() { - self.changed_oauth2.set( - commit_cand - .iter() - .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), - ) - } - if !self.changed_domain.get() { - self.changed_domain.set( - commit_cand - .iter() - .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), - ) - } + // Run any pre-create plugins now with schema validated entries. + // This is important for normalisation of certain types IE class + // or attributes for these checks. + Plugins::run_pre_create(self, &norm_cand, ce).map_err(|e| { + admin_error!("Create operation failed (plugin), {:?}", e); + e + })?; - let cu = self.changed_uuid.as_ptr(); - unsafe { - (*cu).extend(commit_cand.iter().map(|e| e.get_uuid())); - } - trace!( - schema_reload = ?self.changed_schema, - acp_reload = ?self.changed_acp, - oauth2_reload = ?self.changed_oauth2, - domain_reload = ?self.changed_domain, - ); + // We may change from ce.entries later to something else? + let commit_cand = self.be_txn.create(&self.cid, norm_cand).map_err(|e| { + admin_error!("betxn create failure {:?}", e); + e + })?; - // We are complete, finalise logging and return + // Run any post plugins - if ce.ident.is_internal() { - trace!("Create operation success"); - } else { - admin_info!("Create operation success"); - } - Ok(()) - }) + Plugins::run_post_create(self, &commit_cand, ce).map_err(|e| { + admin_error!("Create operation failed (post plugin), {:?}", e); + e + })?; + + // We have finished all plugs and now have a successful operation - flag if + // schema or acp requires reload. + if !self.changed_schema.get() { + self.changed_schema.set(commit_cand.iter().any(|e| { + e.attribute_equality("class", &PVCLASS_CLASSTYPE) + || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) + })) + } + if !self.changed_acp.get() { + self.changed_acp.set( + commit_cand + .iter() + .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), + ) + } + if !self.changed_oauth2.get() { + self.changed_oauth2.set( + commit_cand + .iter() + .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), + ) + } + if !self.changed_domain.get() { + self.changed_domain.set( + commit_cand + .iter() + .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), + ) + } + + let cu = self.changed_uuid.as_ptr(); + unsafe { + (*cu).extend(commit_cand.iter().map(|e| e.get_uuid())); + } + trace!( + schema_reload = ?self.changed_schema, + acp_reload = ?self.changed_acp, + oauth2_reload = ?self.changed_oauth2, + domain_reload = ?self.changed_domain, + ); + + // We are complete, finalise logging and return + + if ce.ident.is_internal() { + trace!("Create operation success"); + } else { + admin_info!("Create operation success"); + } + Ok(()) } #[allow(clippy::cognitive_complexity)] + #[instrument(level = "debug", skip_all)] pub fn delete(&self, de: &DeleteEvent) -> Result<(), OperationError> { - spanned!("server::delete", { - // Do you have access to view all the set members? Reduce based on your - // read permissions and attrs - // THIS IS PRETTY COMPLEX SEE THE DESIGN DOC - // In this case we need a search, but not INTERNAL to keep the same - // associated credentials. - // We only need to retrieve uuid though ... - if !de.ident.is_internal() { - security_info!(name = %de.ident, "delete initiator"); - } + // Do you have access to view all the set members? Reduce based on your + // read permissions and attrs + // THIS IS PRETTY COMPLEX SEE THE DESIGN DOC + // In this case we need a search, but not INTERNAL to keep the same + // associated credentials. + // We only need to retrieve uuid though ... + if !de.ident.is_internal() { + security_info!(name = %de.ident, "delete initiator"); + } - // Now, delete only what you can see - let pre_candidates = self - .impersonate_search_valid(de.filter.clone(), de.filter_orig.clone(), &de.ident) - .map_err(|e| { - admin_error!("delete: error in pre-candidate selection {:?}", e); - e - })?; - - // Apply access controls to reduce the set if required. - // delete_allow_operation - let access = self.get_accesscontrols(); - let op_allow = access - .delete_allow_operation(de, &pre_candidates) - .map_err(|e| { - admin_error!("Failed to check delete access {:?}", e); - e - })?; - if !op_allow { - return Err(OperationError::AccessDenied); - } - - // Is the candidate set empty? - if pre_candidates.is_empty() { - request_error!(filter = ?de.filter, "delete: no candidates match filter"); - return Err(OperationError::NoMatchingEntries); - }; - - if pre_candidates.iter().any(|e| e.mask_tombstone().is_none()) { - admin_warn!("Refusing to delete entries which may be an attempt to bypass replication state machine."); - return Err(OperationError::AccessDenied); - } - - let mut candidates: Vec> = pre_candidates - .iter() - // Invalidate and assign change id's - .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) - .collect(); - - trace!(?candidates, "delete: candidates"); - - // Pre delete plugs - Plugins::run_pre_delete(self, &mut candidates, de).map_err(|e| { - admin_error!("Delete operation failed (plugin), {:?}", e); + // Now, delete only what you can see + let pre_candidates = self + .impersonate_search_valid(de.filter.clone(), de.filter_orig.clone(), &de.ident) + .map_err(|e| { + admin_error!("delete: error in pre-candidate selection {:?}", e); e })?; - trace!(?candidates, "delete: now marking candidates as recycled"); + // Apply access controls to reduce the set if required. + // delete_allow_operation + let access = self.get_accesscontrols(); + let op_allow = access + .delete_allow_operation(de, &pre_candidates) + .map_err(|e| { + admin_error!("Failed to check delete access {:?}", e); + e + })?; + if !op_allow { + return Err(OperationError::AccessDenied); + } - let res: Result>, OperationError> = candidates - .into_iter() - .map(|e| { - e.to_recycled() - .validate(&self.schema) - .map_err(|e| { - admin_error!(err = ?e, "Schema Violation in delete validate"); - OperationError::SchemaViolation(e) - }) - // seal if it worked. - .map(|e| e.seal(&self.schema)) - }) - .collect(); + // Is the candidate set empty? + if pre_candidates.is_empty() { + request_error!(filter = ?de.filter, "delete: no candidates match filter"); + return Err(OperationError::NoMatchingEntries); + }; - let del_cand: Vec> = res?; + if pre_candidates.iter().any(|e| e.mask_tombstone().is_none()) { + admin_warn!("Refusing to delete entries which may be an attempt to bypass replication state machine."); + return Err(OperationError::AccessDenied); + } - self.be_txn - .modify(&self.cid, &pre_candidates, &del_cand) - .map_err(|e| { - // be_txn is dropped, ie aborted here. - admin_error!("Delete operation failed (backend), {:?}", e); - e - })?; + let mut candidates: Vec> = pre_candidates + .iter() + // Invalidate and assign change id's + .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) + .collect(); - // Post delete plugins - Plugins::run_post_delete(self, &del_cand, de).map_err(|e| { - admin_error!("Delete operation failed (plugin), {:?}", e); + trace!(?candidates, "delete: candidates"); + + // Pre delete plugs + Plugins::run_pre_delete(self, &mut candidates, de).map_err(|e| { + admin_error!("Delete operation failed (plugin), {:?}", e); + e + })?; + + trace!(?candidates, "delete: now marking candidates as recycled"); + + let res: Result>, OperationError> = candidates + .into_iter() + .map(|e| { + e.to_recycled() + .validate(&self.schema) + .map_err(|e| { + admin_error!(err = ?e, "Schema Violation in delete validate"); + OperationError::SchemaViolation(e) + }) + // seal if it worked. + .map(|e| e.seal(&self.schema)) + }) + .collect(); + + let del_cand: Vec> = res?; + + self.be_txn + .modify(&self.cid, &pre_candidates, &del_cand) + .map_err(|e| { + // be_txn is dropped, ie aborted here. + admin_error!("Delete operation failed (backend), {:?}", e); e })?; - // We have finished all plugs and now have a successful operation - flag if - // schema or acp requires reload. - if !self.changed_schema.get() { - self.changed_schema.set(del_cand.iter().any(|e| { - e.attribute_equality("class", &PVCLASS_CLASSTYPE) - || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) - })) - } - if !self.changed_acp.get() { - self.changed_acp.set( - del_cand - .iter() - .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), - ) - } - if !self.changed_oauth2.get() { - self.changed_oauth2.set( - del_cand - .iter() - .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), - ) - } - if !self.changed_domain.get() { - self.changed_domain.set( - del_cand - .iter() - .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), - ) - } + // Post delete plugins + Plugins::run_post_delete(self, &del_cand, de).map_err(|e| { + admin_error!("Delete operation failed (plugin), {:?}", e); + e + })?; - let cu = self.changed_uuid.as_ptr(); - unsafe { - (*cu).extend(del_cand.iter().map(|e| e.get_uuid())); - } + // We have finished all plugs and now have a successful operation - flag if + // schema or acp requires reload. + if !self.changed_schema.get() { + self.changed_schema.set(del_cand.iter().any(|e| { + e.attribute_equality("class", &PVCLASS_CLASSTYPE) + || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) + })) + } + if !self.changed_acp.get() { + self.changed_acp.set( + del_cand + .iter() + .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), + ) + } + if !self.changed_oauth2.get() { + self.changed_oauth2.set( + del_cand + .iter() + .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), + ) + } + if !self.changed_domain.get() { + self.changed_domain.set( + del_cand + .iter() + .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), + ) + } - trace!( - schema_reload = ?self.changed_schema, - acp_reload = ?self.changed_acp, - oauth2_reload = ?self.changed_oauth2, - domain_reload = ?self.changed_domain, - ); + let cu = self.changed_uuid.as_ptr(); + unsafe { + (*cu).extend(del_cand.iter().map(|e| e.get_uuid())); + } - // Send result - if de.ident.is_internal() { - trace!("Delete operation success"); - } else { - admin_info!("Delete operation success"); - } - Ok(()) - }) + trace!( + schema_reload = ?self.changed_schema, + acp_reload = ?self.changed_acp, + oauth2_reload = ?self.changed_oauth2, + domain_reload = ?self.changed_domain, + ); + + // Send result + if de.ident.is_internal() { + trace!("Delete operation success"); + } else { + admin_info!("Delete operation success"); + } + Ok(()) } + #[instrument(level = "debug", skip_all)] pub fn purge_tombstones(&self) -> Result<(), OperationError> { - spanned!("server::purge_tombstones", { - // purge everything that is a tombstone. - let cid = self.cid.sub_secs(CHANGELOG_MAX_AGE).map_err(|e| { - admin_error!("Unable to generate search cid {:?}", e); - e - })?; + // purge everything that is a tombstone. + let cid = self.cid.sub_secs(CHANGELOG_MAX_AGE).map_err(|e| { + admin_error!("Unable to generate search cid {:?}", e); + e + })?; - // Delete them - this is a TRUE delete, no going back now! - self.be_txn - .reap_tombstones(&cid) - .map_err(|e| { - admin_error!(err = ?e, "Tombstone purge operation failed (backend)"); - e - }) - .map(|_| { - admin_info!("Tombstone purge operation success"); - }) - }) + // Delete them - this is a TRUE delete, no going back now! + self.be_txn + .reap_tombstones(&cid) + .map_err(|e| { + admin_error!(err = ?e, "Tombstone purge operation failed (backend)"); + e + }) + .map(|_| { + admin_info!("Tombstone purge operation success"); + }) } + #[instrument(level = "debug", skip_all)] pub fn purge_recycled(&self) -> Result<(), OperationError> { - spanned!("server::purge_recycled", { - // Send everything that is recycled to tombstone - // Search all recycled - let cid = self.cid.sub_secs(RECYCLEBIN_MAX_AGE).map_err(|e| { - admin_error!(err = ?e, "Unable to generate search cid"); + // Send everything that is recycled to tombstone + // Search all recycled + let cid = self.cid.sub_secs(RECYCLEBIN_MAX_AGE).map_err(|e| { + admin_error!(err = ?e, "Unable to generate search cid"); + e + })?; + let rc = self.internal_search(filter_all!(f_and!([ + f_eq("class", PVCLASS_RECYCLED.clone()), + f_lt("last_modified_cid", PartialValue::new_cid(cid)), + ])))?; + + if rc.is_empty() { + admin_info!("No recycled present - purge operation success"); + return Ok(()); + } + + // Modify them to strip all avas except uuid + let tombstone_cand: Result, _> = rc + .iter() + .map(|e| { + e.to_tombstone(self.cid.clone()) + .validate(&self.schema) + .map_err(|e| { + admin_error!("Schema Violation in purge_recycled validate: {:?}", e); + OperationError::SchemaViolation(e) + }) + // seal if it worked. + .map(|e| e.seal(&self.schema)) + }) + .collect(); + + let tombstone_cand = tombstone_cand?; + + // Backend Modify + self.be_txn + .modify(&self.cid, &rc, &tombstone_cand) + .map_err(|e| { + admin_error!("Purge recycled operation failed (backend), {:?}", e); e - })?; - let rc = self.internal_search(filter_all!(f_and!([ - f_eq("class", PVCLASS_RECYCLED.clone()), - f_lt("last_modified_cid", PartialValue::new_cid(cid)), - ])))?; - - if rc.is_empty() { - admin_info!("No recycled present - purge operation success"); - return Ok(()); - } - - // Modify them to strip all avas except uuid - let tombstone_cand: Result, _> = rc - .iter() - .map(|e| { - e.to_tombstone(self.cid.clone()) - .validate(&self.schema) - .map_err(|e| { - admin_error!("Schema Violation in purge_recycled validate: {:?}", e); - OperationError::SchemaViolation(e) - }) - // seal if it worked. - .map(|e| e.seal(&self.schema)) - }) - .collect(); - - let tombstone_cand = tombstone_cand?; - - // Backend Modify - self.be_txn - .modify(&self.cid, &rc, &tombstone_cand) - .map_err(|e| { - admin_error!("Purge recycled operation failed (backend), {:?}", e); - e - }) - .map(|_| { - admin_info!("Purge recycled operation success"); - }) - }) + }) + .map(|_| { + admin_info!("Purge recycled operation success"); + }) } - // Should this take a revive event? + #[instrument(level = "debug", skip_all)] pub fn revive_recycled(&self, re: &ReviveRecycledEvent) -> Result<(), OperationError> { - spanned!("server::revive_recycled", { - // Revive an entry to live. This is a specialised function, and draws a lot of - // inspiration from modify. - // - // Access is granted by the ability to ability to search the class=recycled - // and the ability modify + remove that class from the object. - if !re.ident.is_internal() { - security_info!(name = %re.ident, "revive initiator"); + // Revive an entry to live. This is a specialised function, and draws a lot of + // inspiration from modify. + // + // Access is granted by the ability to ability to search the class=recycled + // and the ability modify + remove that class from the object. + if !re.ident.is_internal() { + security_info!(name = %re.ident, "revive initiator"); + } + + // Get the list of pre_candidates, using impersonate search. + let pre_candidates = + self.impersonate_search_valid(re.filter.clone(), re.filter.clone(), &re.ident)?; + + // Is the list empty? + if pre_candidates.is_empty() { + if re.ident.is_internal() { + trace!( + "revive: no candidates match filter ... continuing {:?}", + re.filter + ); + return Ok(()); + } else { + request_error!( + "revive: no candidates match filter, failure {:?}", + re.filter + ); + return Err(OperationError::NoMatchingEntries); } + }; - // Get the list of pre_candidates, using impersonate search. - let pre_candidates = - self.impersonate_search_valid(re.filter.clone(), re.filter.clone(), &re.ident)?; + trace!("revive: pre_candidates -> {:?}", pre_candidates); - // Is the list empty? - if pre_candidates.is_empty() { - if re.ident.is_internal() { - trace!( - "revive: no candidates match filter ... continuing {:?}", - re.filter - ); - return Ok(()); - } else { - request_error!( - "revive: no candidates match filter, failure {:?}", - re.filter - ); - return Err(OperationError::NoMatchingEntries); - } - }; + // Check access against a "fake" modify. + let modlist = ModifyList::new_list(vec![Modify::Removed( + AttrString::from("class"), + PVCLASS_RECYCLED.clone(), + )]); - trace!("revive: pre_candidates -> {:?}", pre_candidates); + let m_valid = modlist.validate(self.get_schema()).map_err(|e| { + admin_error!("revive recycled modlist Schema Violation {:?}", e); + OperationError::SchemaViolation(e) + })?; - // Check access against a "fake" modify. - let modlist = ModifyList::new_list(vec![Modify::Removed( - AttrString::from("class"), - PVCLASS_RECYCLED.clone(), - )]); + let me = + ModifyEvent::new_impersonate(&re.ident, re.filter.clone(), re.filter.clone(), m_valid); - let m_valid = modlist.validate(self.get_schema()).map_err(|e| { - admin_error!("revive recycled modlist Schema Violation {:?}", e); - OperationError::SchemaViolation(e) - })?; - - let me = ModifyEvent::new_impersonate( - &re.ident, - re.filter.clone(), - re.filter.clone(), - m_valid, - ); - - let access = self.get_accesscontrols(); - let op_allow = access - .modify_allow_operation(&me, &pre_candidates) - .map_err(|e| { - admin_error!("Unable to check modify access {:?}", e); - e - })?; - if !op_allow { - return Err(OperationError::AccessDenied); - } - - // Are all of the entries actually recycled? - if pre_candidates.iter().all(|e| e.mask_recycled().is_some()) { - admin_warn!("Refusing to revive entries that are already live!"); - return Err(OperationError::AccessDenied); - } - - // Build the list of mods from directmo, to revive memberships. - let mut dm_mods: HashMap> = - HashMap::with_capacity(pre_candidates.len()); - - for e in &pre_candidates { - // Get this entries uuid. - let u: Uuid = e.get_uuid(); - - if let Some(riter) = e.get_ava_as_refuuid("directmemberof") { - for g_uuid in riter { - dm_mods - .entry(g_uuid) - .and_modify(|mlist| { - let m = Modify::Present( - AttrString::from("member"), - Value::new_refer_r(&u), - ); - mlist.push_mod(m); - }) - .or_insert({ - let m = Modify::Present( - AttrString::from("member"), - Value::new_refer_r(&u), - ); - ModifyList::new_list(vec![m]) - }); - } - } - } - - // clone the writeable entries. - let mut candidates: Vec> = pre_candidates - .iter() - .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) - // Mutate to apply the revive. - .map(|er| er.to_revived()) - .collect(); - - // Are they all revived? - if candidates.iter().all(|e| e.mask_recycled().is_none()) { - admin_error!("Not all candidates were correctly revived, unable to proceed"); - return Err(OperationError::InvalidEntryState); - } - - // Do we need to apply pre-mod? - // Very likely, incase domain has renamed etc. - Plugins::run_pre_modify(self, &mut candidates, &me).map_err(|e| { - admin_error!("Revive operation failed (plugin), {:?}", e); + let access = self.get_accesscontrols(); + let op_allow = access + .modify_allow_operation(&me, &pre_candidates) + .map_err(|e| { + admin_error!("Unable to check modify access {:?}", e); e })?; + if !op_allow { + return Err(OperationError::AccessDenied); + } - // Schema validate - let res: Result>, OperationError> = candidates - .into_iter() - .map(|e| { - e.validate(&self.schema) - .map_err(|e| { - admin_error!("Schema Violation {:?}", e); - OperationError::SchemaViolation(e) + // Are all of the entries actually recycled? + if pre_candidates.iter().all(|e| e.mask_recycled().is_some()) { + admin_warn!("Refusing to revive entries that are already live!"); + return Err(OperationError::AccessDenied); + } + + // Build the list of mods from directmo, to revive memberships. + let mut dm_mods: HashMap> = + HashMap::with_capacity(pre_candidates.len()); + + for e in &pre_candidates { + // Get this entries uuid. + let u: Uuid = e.get_uuid(); + + if let Some(riter) = e.get_ava_as_refuuid("directmemberof") { + for g_uuid in riter { + dm_mods + .entry(g_uuid) + .and_modify(|mlist| { + let m = + Modify::Present(AttrString::from("member"), Value::new_refer_r(&u)); + mlist.push_mod(m); }) - .map(|e| e.seal(&self.schema)) - }) - .collect(); - - let norm_cand: Vec> = res?; - - // build the mod partial - let mp = ModifyPartial { - norm_cand, - pre_candidates, - me: &me, - }; - - // Call modify_apply - self.modify_apply(mp)?; - - // If and only if that succeeds, apply the direct membership modifications - // if possible. - for (g, mods) in dm_mods { - // I think the filter/filter_all shouldn't matter here because the only - // valid direct memberships should be still valid/live references, as refint - // removes anything that was deleted even from recycled entries. - let f = filter_all!(f_eq("uuid", PartialValue::new_uuid(g))); - self.internal_modify(&f, &mods)?; - } - - Ok(()) - }) - } - - // Should this take a revive event? - pub fn revive_recycled_legacy(&self, re: &ReviveRecycledEvent) -> Result<(), OperationError> { - spanned!("server::revive_recycled", { - // Revive an entry to live. This is a specialised function, and draws a lot of - // inspiration from modify. - // - // - // Access is granted by the ability to ability to search the class=recycled - // and the ability modify + remove that class from the object. - - // create the modify for access testing. - // tl;dr, remove the class=recycled - let modlist = ModifyList::new_list(vec![Modify::Removed( - AttrString::from("class"), - PVCLASS_RECYCLED.clone(), - )]); - - let m_valid = modlist.validate(self.get_schema()).map_err(|e| { - admin_error!( - "Schema Violation in revive recycled modlist validate: {:?}", - e - ); - OperationError::SchemaViolation(e) - })?; - - // Get the entries we are about to revive. - // we make a set of per-entry mod lists. A list of lists even ... - let revive_cands = - self.impersonate_search_valid(re.filter.clone(), re.filter.clone(), &re.ident)?; - - let mut dm_mods: HashMap> = - HashMap::with_capacity(revive_cands.len()); - - for e in revive_cands { - // Get this entries uuid. - let u: Uuid = e.get_uuid(); - - if let Some(riter) = e.get_ava_as_refuuid("directmemberof") { - for g_uuid in riter { - dm_mods - .entry(g_uuid) - .and_modify(|mlist| { - let m = Modify::Present( - AttrString::from("member"), - Value::new_refer_r(&u), - ); - mlist.push_mod(m); - }) - .or_insert({ - let m = Modify::Present( - AttrString::from("member"), - Value::new_refer_r(&u), - ); - ModifyList::new_list(vec![m]) - }); - } + .or_insert({ + let m = + Modify::Present(AttrString::from("member"), Value::new_refer_r(&u)); + ModifyList::new_list(vec![m]) + }); } } + } - // Now impersonate the modify - self.impersonate_modify_valid( - re.filter.clone(), - re.filter.clone(), - m_valid, - &re.ident, - )?; - // If and only if that succeeds, apply the direct membership modifications - // if possible. - for (g, mods) in dm_mods { - // I think the filter/filter_all shouldn't matter here because the only - // valid direct memberships should be still valid/live references. - let f = filter_all!(f_eq("uuid", PartialValue::new_uuid(g))); - self.internal_modify(&f, &mods)?; + // clone the writeable entries. + let mut candidates: Vec> = pre_candidates + .iter() + .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) + // Mutate to apply the revive. + .map(|er| er.to_revived()) + .collect(); + + // Are they all revived? + if candidates.iter().all(|e| e.mask_recycled().is_none()) { + admin_error!("Not all candidates were correctly revived, unable to proceed"); + return Err(OperationError::InvalidEntryState); + } + + // Do we need to apply pre-mod? + // Very likely, incase domain has renamed etc. + Plugins::run_pre_modify(self, &mut candidates, &me).map_err(|e| { + admin_error!("Revive operation failed (plugin), {:?}", e); + e + })?; + + // Schema validate + let res: Result>, OperationError> = candidates + .into_iter() + .map(|e| { + e.validate(&self.schema) + .map_err(|e| { + admin_error!("Schema Violation {:?}", e); + OperationError::SchemaViolation(e) + }) + .map(|e| e.seal(&self.schema)) + }) + .collect(); + + let norm_cand: Vec> = res?; + + // build the mod partial + let mp = ModifyPartial { + norm_cand, + pre_candidates, + me: &me, + }; + + // Call modify_apply + self.modify_apply(mp)?; + + // If and only if that succeeds, apply the direct membership modifications + // if possible. + for (g, mods) in dm_mods { + // I think the filter/filter_all shouldn't matter here because the only + // valid direct memberships should be still valid/live references, as refint + // removes anything that was deleted even from recycled entries. + let f = filter_all!(f_eq("uuid", PartialValue::new_uuid(g))); + self.internal_modify(&f, &mods)?; + } + + Ok(()) + } + + #[instrument(level = "debug", skip_all)] + pub fn revive_recycled_legacy(&self, re: &ReviveRecycledEvent) -> Result<(), OperationError> { + // Revive an entry to live. This is a specialised function, and draws a lot of + // inspiration from modify. + // + // + // Access is granted by the ability to ability to search the class=recycled + // and the ability modify + remove that class from the object. + + // create the modify for access testing. + // tl;dr, remove the class=recycled + let modlist = ModifyList::new_list(vec![Modify::Removed( + AttrString::from("class"), + PVCLASS_RECYCLED.clone(), + )]); + + let m_valid = modlist.validate(self.get_schema()).map_err(|e| { + admin_error!( + "Schema Violation in revive recycled modlist validate: {:?}", + e + ); + OperationError::SchemaViolation(e) + })?; + + // Get the entries we are about to revive. + // we make a set of per-entry mod lists. A list of lists even ... + let revive_cands = + self.impersonate_search_valid(re.filter.clone(), re.filter.clone(), &re.ident)?; + + let mut dm_mods: HashMap> = + HashMap::with_capacity(revive_cands.len()); + + for e in revive_cands { + // Get this entries uuid. + let u: Uuid = e.get_uuid(); + + if let Some(riter) = e.get_ava_as_refuuid("directmemberof") { + for g_uuid in riter { + dm_mods + .entry(g_uuid) + .and_modify(|mlist| { + let m = + Modify::Present(AttrString::from("member"), Value::new_refer_r(&u)); + mlist.push_mod(m); + }) + .or_insert({ + let m = + Modify::Present(AttrString::from("member"), Value::new_refer_r(&u)); + ModifyList::new_list(vec![m]) + }); + } } - Ok(()) - }) + } + + // Now impersonate the modify + self.impersonate_modify_valid(re.filter.clone(), re.filter.clone(), m_valid, &re.ident)?; + // If and only if that succeeds, apply the direct membership modifications + // if possible. + for (g, mods) in dm_mods { + // I think the filter/filter_all shouldn't matter here because the only + // valid direct memberships should be still valid/live references. + let f = filter_all!(f_eq("uuid", PartialValue::new_uuid(g))); + self.internal_modify(&f, &mods)?; + } + Ok(()) } /// Unsafety: This is unsafe because you need to be careful about how you handle and check /// the Ok(None) case which occurs during internal operations, and that you DO NOT re-order /// and call multiple pre-applies at the same time, else you can cause DB corruption. + #[instrument(level = "debug", skip_all)] pub(crate) unsafe fn modify_pre_apply<'x>( &self, me: &'x ModifyEvent, ) -> Result>, OperationError> { - spanned!("server::modify_pre_apply", { - // Get the candidates. - // Modify applies a modlist to a filter, so we need to internal search - // then apply. - if !me.ident.is_internal() { - security_info!(name = %me.ident, "modify initiator"); - } + // Get the candidates. + // Modify applies a modlist to a filter, so we need to internal search + // then apply. + if !me.ident.is_internal() { + security_info!(name = %me.ident, "modify initiator"); + } - // Validate input. + // Validate input. - // Is the modlist non zero? - if me.modlist.is_empty() { - request_error!("modify: empty modify request"); - return Err(OperationError::EmptyRequest); - } + // Is the modlist non zero? + if me.modlist.is_empty() { + request_error!("modify: empty modify request"); + return Err(OperationError::EmptyRequest); + } - // Is the modlist valid? - // This is now done in the event transform + // Is the modlist valid? + // This is now done in the event transform - // Is the filter invalid to schema? - // This is now done in the event transform + // Is the filter invalid to schema? + // This is now done in the event transform - // This also checks access controls due to use of the impersonation. - let pre_candidates = self - .impersonate_search_valid(me.filter.clone(), me.filter_orig.clone(), &me.ident) - .map_err(|e| { - admin_error!("modify: error in pre-candidate selection {:?}", e); - e - })?; - - if pre_candidates.is_empty() { - if me.ident.is_internal() { - trace!( - "modify: no candidates match filter ... continuing {:?}", - me.filter - ); - return Ok(None); - } else { - request_error!( - "modify: no candidates match filter, failure {:?}", - me.filter - ); - return Err(OperationError::NoMatchingEntries); - } - }; - - trace!("modify: pre_candidates -> {:?}", pre_candidates); - trace!("modify: modlist -> {:?}", me.modlist); - - // Are we allowed to make the changes we want to? - // modify_allow_operation - let access = self.get_accesscontrols(); - let op_allow = access - .modify_allow_operation(me, &pre_candidates) - .map_err(|e| { - admin_error!("Unable to check modify access {:?}", e); - e - })?; - if !op_allow { - return Err(OperationError::AccessDenied); - } - - // Clone a set of writeables. - // Apply the modlist -> Remember, we have a set of origs - // and the new modified ents. - let mut candidates: Vec> = pre_candidates - .iter() - .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) - .collect(); - - candidates - .iter_mut() - .for_each(|er| er.apply_modlist(&me.modlist)); - - trace!("modify: candidates -> {:?}", candidates); - - // Did any of the candidates now become masked? - if candidates.iter().any(|e| e.mask_recycled_ts().is_none()) { - admin_warn!("Refusing to apply modifications that are attempting to bypass replication state machine."); - return Err(OperationError::AccessDenied); - } - - // Pre mod plugins - // We should probably supply the pre-post cands here. - Plugins::run_pre_modify(self, &mut candidates, me).map_err(|e| { - admin_error!("Pre-Modify operation failed (plugin), {:?}", e); + // This also checks access controls due to use of the impersonation. + let pre_candidates = self + .impersonate_search_valid(me.filter.clone(), me.filter_orig.clone(), &me.ident) + .map_err(|e| { + admin_error!("modify: error in pre-candidate selection {:?}", e); e })?; - // NOTE: There is a potential optimisation here, where if - // candidates == pre-candidates, then we don't need to store anything - // because we effectively just did an assert. However, like all - // optimisations, this could be premature - so we for now, just - // do the CORRECT thing and recommit as we may find later we always - // want to add CSN's or other. - - let res: Result>, OperationError> = candidates - .into_iter() - .map(|entry| { - entry - .validate(&self.schema) - .map_err(|e| { - admin_error!( - "Schema Violation in validation of modify_pre_apply {:?}", - e - ); - OperationError::SchemaViolation(e) - }) - .map(|entry| entry.seal(&self.schema)) - }) - .collect(); - - let norm_cand: Vec> = res?; - - Ok(Some(ModifyPartial { - norm_cand, - pre_candidates, - me, - })) - }) - } - - pub(crate) fn modify_apply(&self, mp: ModifyPartial<'_>) -> Result<(), OperationError> { - spanned!("server::modify_apply", { - let ModifyPartial { - norm_cand, - pre_candidates, - me, - } = mp; - - // Backend Modify - self.be_txn - .modify(&self.cid, &pre_candidates, &norm_cand) - .map_err(|e| { - admin_error!("Modify operation failed (backend), {:?}", e); - e - })?; - - // Post Plugins - // - // memberOf actually wants the pre cand list and the norm_cand list to see what - // changed. Could be optimised, but this is correct still ... - Plugins::run_post_modify(self, &pre_candidates, &norm_cand, me).map_err(|e| { - admin_error!("Post-Modify operation failed (plugin), {:?}", e); - e - })?; - - // We have finished all plugs and now have a successful operation - flag if - // schema or acp requires reload. Remember, this is a modify, so we need to check - // pre and post cands. - if !self.changed_schema.get() { - self.changed_schema.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| { - e.attribute_equality("class", &PVCLASS_CLASSTYPE) - || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) - }), - ) - } - if !self.changed_acp.get() { - self.changed_acp.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), - ) - } - if !self.changed_oauth2.get() { - self.changed_oauth2.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), - ) - } - if !self.changed_domain.get() { - self.changed_domain.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), - ) - } - - let cu = self.changed_uuid.as_ptr(); - unsafe { - (*cu).extend( - norm_cand - .iter() - .map(|e| e.get_uuid()) - .chain(pre_candidates.iter().map(|e| e.get_uuid())), - ); - } - - trace!( - schema_reload = ?self.changed_schema, - acp_reload = ?self.changed_acp, - oauth2_reload = ?self.changed_oauth2, - domain_reload = ?self.changed_domain, - ); - - // return + if pre_candidates.is_empty() { if me.ident.is_internal() { - trace!("Modify operation success"); + trace!( + "modify: no candidates match filter ... continuing {:?}", + me.filter + ); + return Ok(None); } else { - admin_info!("Modify operation success"); + request_error!( + "modify: no candidates match filter, failure {:?}", + me.filter + ); + return Err(OperationError::NoMatchingEntries); } - Ok(()) - }) + }; + + trace!("modify: pre_candidates -> {:?}", pre_candidates); + trace!("modify: modlist -> {:?}", me.modlist); + + // Are we allowed to make the changes we want to? + // modify_allow_operation + let access = self.get_accesscontrols(); + let op_allow = access + .modify_allow_operation(me, &pre_candidates) + .map_err(|e| { + admin_error!("Unable to check modify access {:?}", e); + e + })?; + if !op_allow { + return Err(OperationError::AccessDenied); + } + + // Clone a set of writeables. + // Apply the modlist -> Remember, we have a set of origs + // and the new modified ents. + let mut candidates: Vec> = pre_candidates + .iter() + .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) + .collect(); + + candidates + .iter_mut() + .for_each(|er| er.apply_modlist(&me.modlist)); + + trace!("modify: candidates -> {:?}", candidates); + + // Did any of the candidates now become masked? + if candidates.iter().any(|e| e.mask_recycled_ts().is_none()) { + admin_warn!("Refusing to apply modifications that are attempting to bypass replication state machine."); + return Err(OperationError::AccessDenied); + } + + // Pre mod plugins + // We should probably supply the pre-post cands here. + Plugins::run_pre_modify(self, &mut candidates, me).map_err(|e| { + admin_error!("Pre-Modify operation failed (plugin), {:?}", e); + e + })?; + + // NOTE: There is a potential optimisation here, where if + // candidates == pre-candidates, then we don't need to store anything + // because we effectively just did an assert. However, like all + // optimisations, this could be premature - so we for now, just + // do the CORRECT thing and recommit as we may find later we always + // want to add CSN's or other. + + let res: Result>, OperationError> = candidates + .into_iter() + .map(|entry| { + entry + .validate(&self.schema) + .map_err(|e| { + admin_error!("Schema Violation in validation of modify_pre_apply {:?}", e); + OperationError::SchemaViolation(e) + }) + .map(|entry| entry.seal(&self.schema)) + }) + .collect(); + + let norm_cand: Vec> = res?; + + Ok(Some(ModifyPartial { + norm_cand, + pre_candidates, + me, + })) } + #[instrument(level = "debug", skip_all)] + pub(crate) fn modify_apply(&self, mp: ModifyPartial<'_>) -> Result<(), OperationError> { + let ModifyPartial { + norm_cand, + pre_candidates, + me, + } = mp; + + // Backend Modify + self.be_txn + .modify(&self.cid, &pre_candidates, &norm_cand) + .map_err(|e| { + admin_error!("Modify operation failed (backend), {:?}", e); + e + })?; + + // Post Plugins + // + // memberOf actually wants the pre cand list and the norm_cand list to see what + // changed. Could be optimised, but this is correct still ... + Plugins::run_post_modify(self, &pre_candidates, &norm_cand, me).map_err(|e| { + admin_error!("Post-Modify operation failed (plugin), {:?}", e); + e + })?; + + // We have finished all plugs and now have a successful operation - flag if + // schema or acp requires reload. Remember, this is a modify, so we need to check + // pre and post cands. + if !self.changed_schema.get() { + self.changed_schema.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| { + e.attribute_equality("class", &PVCLASS_CLASSTYPE) + || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) + }), + ) + } + if !self.changed_acp.get() { + self.changed_acp.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), + ) + } + if !self.changed_oauth2.get() { + self.changed_oauth2.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), + ) + } + if !self.changed_domain.get() { + self.changed_domain.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), + ) + } + + let cu = self.changed_uuid.as_ptr(); + unsafe { + (*cu).extend( + norm_cand + .iter() + .map(|e| e.get_uuid()) + .chain(pre_candidates.iter().map(|e| e.get_uuid())), + ); + } + + trace!( + schema_reload = ?self.changed_schema, + acp_reload = ?self.changed_acp, + oauth2_reload = ?self.changed_oauth2, + domain_reload = ?self.changed_domain, + ); + + // return + if me.ident.is_internal() { + trace!("Modify operation success"); + } else { + admin_info!("Modify operation success"); + } + Ok(()) + } + + #[instrument(level = "debug", skip_all)] pub fn modify(&self, me: &ModifyEvent) -> Result<(), OperationError> { - spanned!("server::modify", { - let mp = unsafe { self.modify_pre_apply(me)? }; - if let Some(mp) = mp { - self.modify_apply(mp) - } else { - // No action to apply, the pre-apply said nothing to be done. - Ok(()) - } - }) + let mp = unsafe { self.modify_pre_apply(me)? }; + if let Some(mp) = mp { + self.modify_apply(mp) + } else { + // No action to apply, the pre-apply said nothing to be done. + Ok(()) + } } /// Used in conjunction with internal_batch_modify, to get a pre/post /// pair, where post is pre-configured with metadata to allow /// modificiation before submit back to internal_batch_modify + #[instrument(level = "debug", skip_all)] pub(crate) fn internal_search_writeable( &self, filter: &Filter, ) -> Result, OperationError> { - spanned!("server::internal_search_writeable", { - let f_valid = filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - let se = SearchEvent::new_internal(f_valid); - self.search(&se).map(|vs| { - vs.into_iter() - .map(|e| { - let writeable = e.as_ref().clone().invalidate(self.cid.clone()); - (e, writeable) - }) - .collect() - }) + let f_valid = filter + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + let se = SearchEvent::new_internal(f_valid); + self.search(&se).map(|vs| { + vs.into_iter() + .map(|e| { + let writeable = e.as_ref().clone().invalidate(self.cid.clone()); + (e, writeable) + }) + .collect() }) } @@ -2083,113 +2034,112 @@ impl<'a> QueryServerWriteTransaction<'a> { /// uphold all other plugin and state rules that are important. You /// probably want modify instead. #[allow(clippy::needless_pass_by_value)] + #[instrument(level = "debug", skip_all)] pub(crate) fn internal_batch_modify( &self, pre_candidates: Vec>, candidates: Vec>, ) -> Result<(), OperationError> { - spanned!("server::internal_batch_modify", { - if pre_candidates.is_empty() && candidates.is_empty() { - // No action needed. - return Ok(()); - } + if pre_candidates.is_empty() && candidates.is_empty() { + // No action needed. + return Ok(()); + } - if pre_candidates.len() != candidates.len() { - admin_error!("internal_batch_modify - cand lengths differ"); - return Err(OperationError::InvalidRequestState); - } + if pre_candidates.len() != candidates.len() { + admin_error!("internal_batch_modify - cand lengths differ"); + return Err(OperationError::InvalidRequestState); + } - let res: Result>, OperationError> = candidates - .into_iter() - .map(|e| { - e.validate(&self.schema) - .map_err(|e| { - admin_error!( - "Schema Violation in internal_batch_modify validate: {:?}", - e - ); - OperationError::SchemaViolation(e) - }) - .map(|e| e.seal(&self.schema)) - }) - .collect(); + let res: Result>, OperationError> = candidates + .into_iter() + .map(|e| { + e.validate(&self.schema) + .map_err(|e| { + admin_error!( + "Schema Violation in internal_batch_modify validate: {:?}", + e + ); + OperationError::SchemaViolation(e) + }) + .map(|e| e.seal(&self.schema)) + }) + .collect(); - let norm_cand: Vec> = res?; + let norm_cand: Vec> = res?; - if cfg!(debug_assertions) { - pre_candidates - .iter() - .zip(norm_cand.iter()) - .try_for_each(|(pre, post)| { - if pre.get_uuid() == post.get_uuid() { - Ok(()) - } else { - admin_error!("modify - cand sets not correctly aligned"); - Err(OperationError::InvalidRequestState) - } - })?; - } - - // Backend Modify - self.be_txn - .modify(&self.cid, &pre_candidates, &norm_cand) - .map_err(|e| { - admin_error!("Modify operation failed (backend), {:?}", e); - e + if cfg!(debug_assertions) { + pre_candidates + .iter() + .zip(norm_cand.iter()) + .try_for_each(|(pre, post)| { + if pre.get_uuid() == post.get_uuid() { + Ok(()) + } else { + admin_error!("modify - cand sets not correctly aligned"); + Err(OperationError::InvalidRequestState) + } })?; + } - if !self.changed_schema.get() { - self.changed_schema.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| { - e.attribute_equality("class", &PVCLASS_CLASSTYPE) - || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) - }), - ) - } - if !self.changed_acp.get() { - self.changed_acp.set( - norm_cand - .iter() - .chain(pre_candidates.iter().map(|e| e.as_ref())) - .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), - ) - } - if !self.changed_oauth2.get() { - self.changed_oauth2.set( - norm_cand - .iter() - .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), - ) - } - if !self.changed_domain.get() { - self.changed_domain.set( - norm_cand - .iter() - .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), - ) - } - let cu = self.changed_uuid.as_ptr(); - unsafe { - (*cu).extend( - norm_cand - .iter() - .map(|e| e.get_uuid()) - .chain(pre_candidates.iter().map(|e| e.get_uuid())), - ); - } - trace!( - schema_reload = ?self.changed_schema, - acp_reload = ?self.changed_acp, - oauth2_reload = ?self.changed_oauth2, - domain_reload = ?self.changed_domain, + // Backend Modify + self.be_txn + .modify(&self.cid, &pre_candidates, &norm_cand) + .map_err(|e| { + admin_error!("Modify operation failed (backend), {:?}", e); + e + })?; + + if !self.changed_schema.get() { + self.changed_schema.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| { + e.attribute_equality("class", &PVCLASS_CLASSTYPE) + || e.attribute_equality("class", &PVCLASS_ATTRIBUTETYPE) + }), + ) + } + if !self.changed_acp.get() { + self.changed_acp.set( + norm_cand + .iter() + .chain(pre_candidates.iter().map(|e| e.as_ref())) + .any(|e| e.attribute_equality("class", &PVCLASS_ACP)), + ) + } + if !self.changed_oauth2.get() { + self.changed_oauth2.set( + norm_cand + .iter() + .any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)), + ) + } + if !self.changed_domain.get() { + self.changed_domain.set( + norm_cand + .iter() + .any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)), + ) + } + let cu = self.changed_uuid.as_ptr(); + unsafe { + (*cu).extend( + norm_cand + .iter() + .map(|e| e.get_uuid()) + .chain(pre_candidates.iter().map(|e| e.get_uuid())), ); + } + trace!( + schema_reload = ?self.changed_schema, + acp_reload = ?self.changed_acp, + oauth2_reload = ?self.changed_oauth2, + domain_reload = ?self.changed_domain, + ); - trace!("Modify operation success"); - Ok(()) - }) + trace!("Modify operation success"); + Ok(()) } pub(crate) fn get_dyngroup_cache(&self) -> &mut DynGroupCache { @@ -2200,149 +2150,143 @@ impl<'a> QueryServerWriteTransaction<'a> { } /// Migrate 2 to 3 changes the name, domain_name types from iutf8 to iname. + #[instrument(level = "debug", skip_all)] pub fn migrate_2_to_3(&self) -> Result<(), OperationError> { - spanned!("server::migrate_2_to_3", { - admin_warn!("starting 2 to 3 migration. THIS MAY TAKE A LONG TIME!"); - // Get all entries where pres name or domain_name. INCLUDE TS + RECYCLE. + admin_warn!("starting 2 to 3 migration. THIS MAY TAKE A LONG TIME!"); + // Get all entries where pres name or domain_name. INCLUDE TS + RECYCLE. - let filt = filter_all!(f_or!([f_pres("name"), f_pres("domain_name"),])); + let filt = filter_all!(f_or!([f_pres("name"), f_pres("domain_name"),])); - let pre_candidates = self.internal_search(filt).map_err(|e| { - admin_error!(err = ?e, "migrate_2_to_3 internal search failure"); - e - })?; + let pre_candidates = self.internal_search(filt).map_err(|e| { + admin_error!(err = ?e, "migrate_2_to_3 internal search failure"); + e + })?; - // If there is nothing, we donn't need to do anything. - if pre_candidates.is_empty() { - admin_info!("migrate_2_to_3 no entries to migrate, complete"); - return Ok(()); + // If there is nothing, we donn't need to do anything. + if pre_candidates.is_empty() { + admin_info!("migrate_2_to_3 no entries to migrate, complete"); + return Ok(()); + } + + // Change the value type. + let mut candidates: Vec> = pre_candidates + .iter() + .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) + .collect(); + + candidates.iter_mut().try_for_each(|er| { + let nvs = if let Some(vs) = er.get_ava_set("name") { + vs.migrate_iutf8_iname()? + } else { + None + }; + if let Some(nvs) = nvs { + er.set_ava_set("name", nvs) } - // Change the value type. - let mut candidates: Vec> = pre_candidates - .iter() - .map(|er| er.as_ref().clone().invalidate(self.cid.clone())) - .collect(); - - candidates.iter_mut().try_for_each(|er| { - let nvs = if let Some(vs) = er.get_ava_set("name") { - vs.migrate_iutf8_iname()? - } else { - None - }; - if let Some(nvs) = nvs { - er.set_ava_set("name", nvs) - } - - let nvs = if let Some(vs) = er.get_ava_set("domain_name") { - vs.migrate_iutf8_iname()? - } else { - None - }; - if let Some(nvs) = nvs { - er.set_ava_set("domain_name", nvs) - } - - Ok(()) - })?; - - // Schema check all. - let res: Result>, SchemaError> = candidates - .into_iter() - .map(|e| e.validate(&self.schema).map(|e| e.seal(&self.schema))) - .collect(); - - let norm_cand: Vec> = match res { - Ok(v) => v, - Err(e) => { - admin_error!("migrate_2_to_3 schema error -> {:?}", e); - return Err(OperationError::SchemaViolation(e)); - } + let nvs = if let Some(vs) = er.get_ava_set("domain_name") { + vs.migrate_iutf8_iname()? + } else { + None }; + if let Some(nvs) = nvs { + er.set_ava_set("domain_name", nvs) + } - // Write them back. - self.be_txn - .modify(&self.cid, &pre_candidates, &norm_cand) - .map_err(|e| { - admin_error!("migrate_2_to_3 modification failure -> {:?}", e); - e - }) - // Complete - }) + Ok(()) + })?; + + // Schema check all. + let res: Result>, SchemaError> = candidates + .into_iter() + .map(|e| e.validate(&self.schema).map(|e| e.seal(&self.schema))) + .collect(); + + let norm_cand: Vec> = match res { + Ok(v) => v, + Err(e) => { + admin_error!("migrate_2_to_3 schema error -> {:?}", e); + return Err(OperationError::SchemaViolation(e)); + } + }; + + // Write them back. + self.be_txn + .modify(&self.cid, &pre_candidates, &norm_cand) + .map_err(|e| { + admin_error!("migrate_2_to_3 modification failure -> {:?}", e); + e + }) + // Complete } /// Migrate 3 to 4 - this triggers a regen of the domains security token /// as we previously did not have it in the entry. + #[instrument(level = "debug", skip_all)] pub fn migrate_3_to_4(&self) -> Result<(), OperationError> { - spanned!("server::migrate_3_to_4", { - admin_warn!("starting 3 to 4 migration."); - let filter = filter!(f_eq("uuid", (*PVUUID_DOMAIN_INFO).clone())); - let modlist = ModifyList::new_purge("domain_token_key"); - self.internal_modify(&filter, &modlist) - // Complete - }) + admin_warn!("starting 3 to 4 migration."); + let filter = filter!(f_eq("uuid", (*PVUUID_DOMAIN_INFO).clone())); + let modlist = ModifyList::new_purge("domain_token_key"); + self.internal_modify(&filter, &modlist) + // Complete } /// Migrate 4 to 5 - this triggers a regen of all oauth2 RS es256 der keys /// as we previously did not generate them on entry creation. + #[instrument(level = "debug", skip_all)] pub fn migrate_4_to_5(&self) -> Result<(), OperationError> { - spanned!("server::migrate_4_to_5", { - admin_warn!("starting 4 to 5 migration."); - let filter = filter!(f_and!([ - f_eq("class", (*PVCLASS_OAUTH2_RS).clone()), - f_andnot(f_pres("es256_private_key_der")), - ])); - let modlist = ModifyList::new_purge("es256_private_key_der"); - self.internal_modify(&filter, &modlist) - // Complete - }) + admin_warn!("starting 4 to 5 migration."); + let filter = filter!(f_and!([ + f_eq("class", (*PVCLASS_OAUTH2_RS).clone()), + f_andnot(f_pres("es256_private_key_der")), + ])); + let modlist = ModifyList::new_purge("es256_private_key_der"); + self.internal_modify(&filter, &modlist) + // Complete } /// Migrate 5 to 6 - This updates the domain info item to reset the token /// keys based on the new encryption types. + #[instrument(level = "debug", skip_all)] pub fn migrate_5_to_6(&self) -> Result<(), OperationError> { - spanned!("server::migrate_5_to_6", { - admin_warn!("starting 5 to 6 migration."); - let filter = filter!(f_eq("uuid", (*PVUUID_DOMAIN_INFO).clone())); - let mut modlist = ModifyList::new_purge("domain_token_key"); - // We need to also push the version here so that we pass schema. - modlist.push_mod(Modify::Present( - AttrString::from("version"), - Value::Uint32(0), - )); - self.internal_modify(&filter, &modlist) - // Complete - }) + admin_warn!("starting 5 to 6 migration."); + let filter = filter!(f_eq("uuid", (*PVUUID_DOMAIN_INFO).clone())); + let mut modlist = ModifyList::new_purge("domain_token_key"); + // We need to also push the version here so that we pass schema. + modlist.push_mod(Modify::Present( + AttrString::from("version"), + Value::Uint32(0), + )); + self.internal_modify(&filter, &modlist) + // Complete } /// Migrate 6 to 7 /// /// Modify accounts that are not persons, to be service accounts so that the extension /// rules remain valid. + #[instrument(level = "debug", skip_all)] pub fn migrate_6_to_7(&self) -> Result<(), OperationError> { - spanned!("server::migrate_6_to_7", { - admin_warn!("starting 6 to 7 migration."); - let filter = filter!(f_and!([ - f_eq("class", (*PVCLASS_ACCOUNT).clone()), - f_andnot(f_eq("class", (*PVCLASS_PERSON).clone())), - ])); - let modlist = ModifyList::new_append("class", Value::new_class("service_account")); - self.internal_modify(&filter, &modlist) - // Complete - }) + admin_warn!("starting 6 to 7 migration."); + let filter = filter!(f_and!([ + f_eq("class", (*PVCLASS_ACCOUNT).clone()), + f_andnot(f_eq("class", (*PVCLASS_PERSON).clone())), + ])); + let modlist = ModifyList::new_append("class", Value::new_class("service_account")); + self.internal_modify(&filter, &modlist) + // Complete } /// Migrate 7 to 8 /// /// Touch all service accounts to trigger a regen of their es256 jws keys for api tokens + #[instrument(level = "debug", skip_all)] pub fn migrate_7_to_8(&self) -> Result<(), OperationError> { - spanned!("server::migrate_7_to_8", { - admin_warn!("starting 7 to 8 migration."); - let filter = filter!(f_eq("class", (*PVCLASS_SERVICE_ACCOUNT).clone())); - let modlist = ModifyList::new_append("class", Value::new_class("service_account")); - self.internal_modify(&filter, &modlist) - // Complete - }) + admin_warn!("starting 7 to 8 migration."); + let filter = filter!(f_eq("class", (*PVCLASS_SERVICE_ACCOUNT).clone())); + let modlist = ModifyList::new_append("class", Value::new_class("service_account")); + self.internal_modify(&filter, &modlist) + // Complete } // These are where searches and other actions are actually implemented. This @@ -2367,21 +2311,20 @@ impl<'a> QueryServerWriteTransaction<'a> { self.delete(&de) } + #[instrument(level = "debug", skip_all)] pub fn internal_modify( &self, filter: &Filter, modlist: &ModifyList, ) -> Result<(), OperationError> { - spanned!("server::internal_modify", { - let f_valid = filter - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - let m_valid = modlist - .validate(self.get_schema()) - .map_err(OperationError::SchemaViolation)?; - let me = ModifyEvent::new_internal(f_valid, m_valid); - self.modify(&me) - }) + let f_valid = filter + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + let m_valid = modlist + .validate(self.get_schema()) + .map_err(OperationError::SchemaViolation)?; + let me = ModifyEvent::new_internal(f_valid, m_valid); + self.modify(&me) } pub fn impersonate_modify_valid( @@ -2461,18 +2404,17 @@ impl<'a> QueryServerWriteTransaction<'a> { } */ + #[instrument(level = "debug", skip_all)] pub fn internal_migrate_or_create_str(&self, e_str: &str) -> Result<(), OperationError> { - let res = spanned!("server::internal_migrate_or_create_str", { - Entry::from_proto_entry_str(e_str, self) - /* - .and_then(|e: Entry| { - let schema = self.get_schema(); - e.validate(schema).map_err(OperationError::SchemaViolation) - }) - */ - .and_then(|e: Entry| self.internal_migrate_or_create(e)) - }); - trace!(?res, "internal_migrate_or_create_str -> result"); + let res = Entry::from_proto_entry_str(e_str, self) + /* + .and_then(|e: Entry| { + let schema = self.get_schema(); + e.validate(schema).map_err(OperationError::SchemaViolation) + }) + */ + .and_then(|e: Entry| self.internal_migrate_or_create(e)); + trace!(?res); debug_assert!(res.is_ok()); res } @@ -3024,25 +2966,24 @@ impl<'a> QueryServerWriteTransaction<'a> { } /// Pulls the domain name from the database and updates the DomainInfo data in memory + #[instrument(level = "debug", skip_all)] fn reload_domain_info(&mut self) -> Result<(), OperationError> { - spanned!("server::reload_domain_info", { - let domain_name = self.get_db_domain_name()?; - let display_name = self.get_db_domain_display_name()?; - let mut_d_info = self.d_info.get_mut(); - if mut_d_info.d_name != domain_name { - admin_warn!( - "Using domain name from the database {} - was {} in memory", - domain_name, - mut_d_info.d_name, - ); - admin_warn!( + let domain_name = self.get_db_domain_name()?; + let display_name = self.get_db_domain_display_name()?; + let mut_d_info = self.d_info.get_mut(); + if mut_d_info.d_name != domain_name { + admin_warn!( + "Using domain name from the database {} - was {} in memory", + domain_name, + mut_d_info.d_name, + ); + admin_warn!( "If you think this is an error, see https://kanidm.github.io/kanidm/stable/administrivia.html#rename-the-domain" ); - mut_d_info.d_name = domain_name; - } - mut_d_info.d_display = display_name; - Ok(()) - }) + mut_d_info.d_name = domain_name; + } + mut_d_info.d_display = display_name; + Ok(()) } /// Initiate a domain display name change process. This isn't particularly scary @@ -3183,13 +3124,15 @@ impl<'a> QueryServerWriteTransaction<'a> { #[cfg(test)] mod tests { + use std::sync::Arc; + use std::time::Duration; + + use kanidm_proto::v1::SchemaError; + use crate::credential::policy::CryptoPolicy; use crate::credential::Credential; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent, ReviveRecycledEvent, SearchEvent}; use crate::prelude::*; - use kanidm_proto::v1::SchemaError; - use std::sync::Arc; - use std::time::Duration; #[test] fn test_qs_create_user() { diff --git a/kanidmd/idm/src/status.rs b/kanidmd/idm/src/status.rs index 2f700813f..9ea46dd41 100644 --- a/kanidmd/idm/src/status.rs +++ b/kanidmd/idm/src/status.rs @@ -1,8 +1,9 @@ //! An actor that shows the servers current status and statistics. (TODO). -use crate::prelude::*; use uuid::Uuid; +use crate::prelude::*; + pub struct StatusRequestEvent { pub eventid: Uuid, } diff --git a/kanidmd/idm/src/utils.rs b/kanidmd/idm/src/utils.rs index 70922a4ff..d28ceb75c 100644 --- a/kanidmd/idm/src/utils.rs +++ b/kanidmd/idm/src/utils.rs @@ -1,26 +1,23 @@ -use hashbrown::HashSet; -use std::io::ErrorKind; -use std::path::PathBuf; -use std::time::{Duration, SystemTime}; - -use filetime::FileTime; -use touch::file as touch_file; -use uuid::{Builder, Uuid}; - -use rand::distributions::Distribution; -use rand::{thread_rng, Rng}; - #[cfg(not(target_family = "windows"))] use std::fs::Metadata; +use std::io::ErrorKind; #[cfg(target_os = "linux")] use std::os::linux::fs::MetadataExt; #[cfg(target_os = "macos")] use std::os::macos::fs::MetadataExt; +use std::path::PathBuf; +use std::time::{Duration, SystemTime}; + +use filetime::FileTime; +use hashbrown::HashSet; +use rand::distributions::Distribution; +use rand::{thread_rng, Rng}; +use touch::file as touch_file; // #[cfg(target_os = "windows")] // use std::os::windows::fs::MetadataExt; - #[cfg(target_family = "unix")] use users::{get_current_gid, get_current_uid}; +use uuid::{Builder, Uuid}; #[derive(Debug)] pub struct DistinctAlpha; @@ -188,10 +185,12 @@ pub fn file_permissions_readonly(meta: &Metadata) -> bool { #[cfg(test)] mod tests { - use crate::utils::{uuid_from_duration, uuid_to_gid_u32}; use std::time::Duration; + use uuid::Uuid; + use crate::utils::{uuid_from_duration, uuid_to_gid_u32}; + #[test] fn test_utils_uuid_from_duration() { let u1 = uuid_from_duration(Duration::from_secs(1), [0xff; 4]); diff --git a/kanidmd/idm/src/value.rs b/kanidmd/idm/src/value.rs index 883f0b398..258a64672 100644 --- a/kanidmd/idm/src/value.rs +++ b/kanidmd/idm/src/value.rs @@ -3,29 +3,26 @@ //! typed values, allows their comparison, filtering and more. It also has the code for serialising //! these into a form for the backend that can be persistent into the [`Backend`](crate::be::Backend). -use crate::be::dbentry::DbIdentSpn; -use crate::credential::Credential; -use crate::identity::IdentityId; -use crate::repl::cid::Cid; -use kanidm_proto::v1::Filter as ProtoFilter; - -use compact_jwt::JwsSigner; -use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; use std::convert::TryFrom; use std::fmt; use std::str::FromStr; use std::time::Duration; + +use compact_jwt::JwsSigner; +use kanidm_proto::v1::Filter as ProtoFilter; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use sshkeys::PublicKey as SshPublicKey; use time::OffsetDateTime; use url::Url; use uuid::Uuid; +use webauthn_rs::prelude::{DeviceKey as DeviceKeyV4, Passkey as PasskeyV4}; -use sshkeys::PublicKey as SshPublicKey; - -use regex::Regex; - -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; +use crate::be::dbentry::DbIdentSpn; +use crate::credential::Credential; +use crate::identity::IdentityId; +use crate::repl::cid::Cid; lazy_static! { pub static ref SPN_RE: Regex = { diff --git a/kanidmd/idm/src/valueset/address.rs b/kanidmd/idm/src/valueset/address.rs index 7c0db4f7a..74c01c37d 100644 --- a/kanidmd/idm/src/valueset/address.rs +++ b/kanidmd/idm/src/valueset/address.rs @@ -1,12 +1,12 @@ +use std::collections::BTreeSet; + +use smolset::SmolSet; + use crate::be::dbvalue::DbValueAddressV1; use crate::prelude::*; use crate::schema::SchemaAttribute; use crate::value::Address; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; - -use std::collections::BTreeSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetAddress { diff --git a/kanidmd/idm/src/valueset/binary.rs b/kanidmd/idm/src/valueset/binary.rs index 2b2d65fec..8e31ad374 100644 --- a/kanidmd/idm/src/valueset/binary.rs +++ b/kanidmd/idm/src/valueset/binary.rs @@ -1,12 +1,12 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; - use std::collections::btree_map::Entry as BTreeEntry; use std::collections::BTreeMap; +use smolset::SmolSet; + +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; + #[derive(Debug, Clone)] pub struct ValueSetPrivateBinary { set: SmolSet<[Vec; 1]>, diff --git a/kanidmd/idm/src/valueset/bool.rs b/kanidmd/idm/src/valueset/bool.rs index 3f1efda3c..b5e8ba7a5 100644 --- a/kanidmd/idm/src/valueset/bool.rs +++ b/kanidmd/idm/src/valueset/bool.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetBool { diff --git a/kanidmd/idm/src/valueset/cid.rs b/kanidmd/idm/src/valueset/cid.rs index a864cbede..36aedacc9 100644 --- a/kanidmd/idm/src/valueset/cid.rs +++ b/kanidmd/idm/src/valueset/cid.rs @@ -1,11 +1,10 @@ +use smolset::SmolSet; + use crate::be::dbvalue::DbCidV1; use crate::prelude::*; use crate::repl::cid::Cid; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; - -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetCid { diff --git a/kanidmd/idm/src/valueset/cred.rs b/kanidmd/idm/src/valueset/cred.rs index 366149430..a22f0b108 100644 --- a/kanidmd/idm/src/valueset/cred.rs +++ b/kanidmd/idm/src/valueset/cred.rs @@ -1,18 +1,15 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use std::collections::btree_map::Entry as BTreeEntry; use std::collections::BTreeMap; +use webauthn_rs::prelude::{DeviceKey as DeviceKeyV4, Passkey as PasskeyV4}; + use crate::be::dbvalue::{ DbValueCredV1, DbValueDeviceKeyV1, DbValueIntentTokenStateV1, DbValuePasskeyV1, }; use crate::credential::Credential; -use crate::valueset::IntentTokenState; - -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, IntentTokenState, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetCredential { diff --git a/kanidmd/idm/src/valueset/datetime.rs b/kanidmd/idm/src/valueset/datetime.rs index 8ea8ab6ee..4741fdf02 100644 --- a/kanidmd/idm/src/valueset/datetime.rs +++ b/kanidmd/idm/src/valueset/datetime.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use smolset::SmolSet; use time::OffsetDateTime; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; + #[derive(Debug, Clone)] pub struct ValueSetDateTime { set: SmolSet<[OffsetDateTime; 1]>, diff --git a/kanidmd/idm/src/valueset/iname.rs b/kanidmd/idm/src/valueset/iname.rs index b44308a97..a9d35b99e 100644 --- a/kanidmd/idm/src/valueset/iname.rs +++ b/kanidmd/idm/src/valueset/iname.rs @@ -1,10 +1,9 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use std::collections::BTreeSet; +use crate::prelude::*; +use crate::schema::SchemaAttribute; use crate::value::INAME_RE; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetIname { diff --git a/kanidmd/idm/src/valueset/index.rs b/kanidmd/idm/src/valueset/index.rs index 1969b0b7e..7aebcb66a 100644 --- a/kanidmd/idm/src/valueset/index.rs +++ b/kanidmd/idm/src/valueset/index.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetIndex { diff --git a/kanidmd/idm/src/valueset/iutf8.rs b/kanidmd/idm/src/valueset/iutf8.rs index d6b4da6d8..8fd50d56e 100644 --- a/kanidmd/idm/src/valueset/iutf8.rs +++ b/kanidmd/idm/src/valueset/iutf8.rs @@ -1,10 +1,9 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use std::collections::BTreeSet; use super::iname::ValueSetIname; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetIutf8 { diff --git a/kanidmd/idm/src/valueset/json.rs b/kanidmd/idm/src/valueset/json.rs index 6f234892f..09449f302 100644 --- a/kanidmd/idm/src/valueset/json.rs +++ b/kanidmd/idm/src/valueset/json.rs @@ -1,10 +1,10 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use kanidm_proto::v1::Filter as ProtoFilter; use smolset::SmolSet; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; + #[derive(Debug, Clone)] pub struct ValueSetJsonFilter { set: SmolSet<[ProtoFilter; 1]>, diff --git a/kanidmd/idm/src/valueset/jws.rs b/kanidmd/idm/src/valueset/jws.rs index 3d85ffefd..063099050 100644 --- a/kanidmd/idm/src/valueset/jws.rs +++ b/kanidmd/idm/src/valueset/jws.rs @@ -1,10 +1,9 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; +use compact_jwt::{JwaAlg, JwsSigner}; use hashbrown::HashSet; -use compact_jwt::{JwaAlg, JwsSigner}; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetJwsKeyEs256 { diff --git a/kanidmd/idm/src/valueset/mod.rs b/kanidmd/idm/src/valueset/mod.rs index de9e054c0..65ce03f6f 100644 --- a/kanidmd/idm/src/valueset/mod.rs +++ b/kanidmd/idm/src/valueset/mod.rs @@ -1,27 +1,21 @@ +use std::collections::{BTreeMap, BTreeSet}; + +use compact_jwt::JwsSigner; +use dyn_clone::DynClone; +use hashbrown::HashSet; +use kanidm_proto::v1::Filter as ProtoFilter; +use smolset::SmolSet; +use time::OffsetDateTime; +// use std::fmt::Debug; +use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; +use webauthn_rs::prelude::Passkey as PasskeyV4; + +use crate::be::dbvalue::DbValueSetV2; use crate::credential::Credential; use crate::prelude::*; use crate::repl::cid::Cid; use crate::schema::SchemaAttribute; - -use crate::be::dbvalue::DbValueSetV2; -use crate::value::Address; -use crate::value::IntentTokenState; -use crate::value::Session; -use compact_jwt::JwsSigner; - -use kanidm_proto::v1::Filter as ProtoFilter; - -use std::collections::{BTreeMap, BTreeSet}; - -use dyn_clone::DynClone; -use hashbrown::HashSet; -use smolset::SmolSet; -// use std::fmt::Debug; - -use webauthn_rs::prelude::DeviceKey as DeviceKeyV4; -use webauthn_rs::prelude::Passkey as PasskeyV4; - -use time::OffsetDateTime; +use crate::value::{Address, IntentTokenState, Session}; mod address; mod binary; @@ -69,8 +63,7 @@ pub use self::syntax::ValueSetSyntax; pub use self::uint32::ValueSetUint32; pub use self::url::ValueSetUrl; pub use self::utf8::ValueSetUtf8; -pub use self::uuid::ValueSetRefer; -pub use self::uuid::ValueSetUuid; +pub use self::uuid::{ValueSetRefer, ValueSetUuid}; pub type ValueSet = Box; diff --git a/kanidmd/idm/src/valueset/nsuniqueid.rs b/kanidmd/idm/src/valueset/nsuniqueid.rs index ee1e69984..b2f06d403 100644 --- a/kanidmd/idm/src/valueset/nsuniqueid.rs +++ b/kanidmd/idm/src/valueset/nsuniqueid.rs @@ -1,9 +1,9 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; use crate::value::NSUNIQUEID_RE; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetNsUniqueId { diff --git a/kanidmd/idm/src/valueset/oauth.rs b/kanidmd/idm/src/valueset/oauth.rs index 10f7f6c7c..e6af6d08c 100644 --- a/kanidmd/idm/src/valueset/oauth.rs +++ b/kanidmd/idm/src/valueset/oauth.rs @@ -1,15 +1,11 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use std::collections::BTreeSet; +use std::collections::btree_map::Entry as BTreeEntry; +use std::collections::{BTreeMap, BTreeSet}; use crate::be::dbvalue::DbValueOauthScopeMapV1; -use crate::valueset::uuid_to_proto_string; -use std::collections::btree_map::Entry as BTreeEntry; -use std::collections::BTreeMap; - +use crate::prelude::*; +use crate::schema::SchemaAttribute; use crate::value::OAUTHSCOPE_RE; +use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetOauthScope { diff --git a/kanidmd/idm/src/valueset/restricted.rs b/kanidmd/idm/src/valueset/restricted.rs index 9a12bdc18..3f680977d 100644 --- a/kanidmd/idm/src/valueset/restricted.rs +++ b/kanidmd/idm/src/valueset/restricted.rs @@ -1,8 +1,8 @@ +use std::collections::BTreeSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use std::collections::BTreeSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetRestricted { diff --git a/kanidmd/idm/src/valueset/secret.rs b/kanidmd/idm/src/valueset/secret.rs index 2482b8b32..c906eeab2 100644 --- a/kanidmd/idm/src/valueset/secret.rs +++ b/kanidmd/idm/src/valueset/secret.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetSecret { diff --git a/kanidmd/idm/src/valueset/session.rs b/kanidmd/idm/src/valueset/session.rs index 0cd6353c3..49a26db99 100644 --- a/kanidmd/idm/src/valueset/session.rs +++ b/kanidmd/idm/src/valueset/session.rs @@ -1,15 +1,14 @@ +use std::collections::btree_map::Entry as BTreeEntry; +use std::collections::BTreeMap; + +use time::OffsetDateTime; + use crate::be::dbvalue::{DbValueIdentityId, DbValueSession}; use crate::identity::IdentityId; use crate::prelude::*; use crate::schema::SchemaAttribute; use crate::value::Session; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use std::collections::btree_map::Entry as BTreeEntry; -use std::collections::BTreeMap; -use time::OffsetDateTime; - -use crate::valueset::uuid_to_proto_string; +use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetSession { diff --git a/kanidmd/idm/src/valueset/spn.rs b/kanidmd/idm/src/valueset/spn.rs index 489e27cd5..6b001a71b 100644 --- a/kanidmd/idm/src/valueset/spn.rs +++ b/kanidmd/idm/src/valueset/spn.rs @@ -1,9 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; - -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetSpn { diff --git a/kanidmd/idm/src/valueset/ssh.rs b/kanidmd/idm/src/valueset/ssh.rs index f9d449ce9..eab58aad8 100644 --- a/kanidmd/idm/src/valueset/ssh.rs +++ b/kanidmd/idm/src/valueset/ssh.rs @@ -1,11 +1,10 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use std::collections::btree_map::Entry as BTreeEntry; use std::collections::BTreeMap; use crate::be::dbvalue::DbValueTaggedStringV1; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetSshKey { diff --git a/kanidmd/idm/src/valueset/syntax.rs b/kanidmd/idm/src/valueset/syntax.rs index 098211442..c094db468 100644 --- a/kanidmd/idm/src/valueset/syntax.rs +++ b/kanidmd/idm/src/valueset/syntax.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetSyntax { diff --git a/kanidmd/idm/src/valueset/uint32.rs b/kanidmd/idm/src/valueset/uint32.rs index f978de79b..f82a31b28 100644 --- a/kanidmd/idm/src/valueset/uint32.rs +++ b/kanidmd/idm/src/valueset/uint32.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetUint32 { diff --git a/kanidmd/idm/src/valueset/url.rs b/kanidmd/idm/src/valueset/url.rs index ec3993edd..b011425f8 100644 --- a/kanidmd/idm/src/valueset/url.rs +++ b/kanidmd/idm/src/valueset/url.rs @@ -1,8 +1,8 @@ +use smolset::SmolSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use smolset::SmolSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetUrl { diff --git a/kanidmd/idm/src/valueset/utf8.rs b/kanidmd/idm/src/valueset/utf8.rs index 04e18c4e2..6d04ae262 100644 --- a/kanidmd/idm/src/valueset/utf8.rs +++ b/kanidmd/idm/src/valueset/utf8.rs @@ -1,8 +1,8 @@ +use std::collections::BTreeSet; + use crate::prelude::*; use crate::schema::SchemaAttribute; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; -use std::collections::BTreeSet; +use crate::valueset::{DbValueSetV2, ValueSet}; #[derive(Debug, Clone)] pub struct ValueSetUtf8 { diff --git a/kanidmd/idm/src/valueset/uuid.rs b/kanidmd/idm/src/valueset/uuid.rs index dbdcac214..bac7933a2 100644 --- a/kanidmd/idm/src/valueset/uuid.rs +++ b/kanidmd/idm/src/valueset/uuid.rs @@ -1,12 +1,11 @@ -use crate::prelude::*; -use crate::schema::SchemaAttribute; -use crate::valueset::uuid_to_proto_string; -use crate::valueset::DbValueSetV2; -use crate::valueset::ValueSet; use std::collections::BTreeSet; use smolset::SmolSet; +use crate::prelude::*; +use crate::schema::SchemaAttribute; +use crate::valueset::{uuid_to_proto_string, DbValueSetV2, ValueSet}; + #[derive(Debug, Clone)] pub struct ValueSetUuid { set: SmolSet<[Uuid; 1]>, diff --git a/kanidmd/score/Cargo.toml b/kanidmd/score/Cargo.toml index 3743627a2..ff5160d11 100644 --- a/kanidmd/score/Cargo.toml +++ b/kanidmd/score/Cargo.toml @@ -1,52 +1,52 @@ [package] name = "score" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Server Library and Binary" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +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 [dependencies] -async-std = { version = "^1.12.0", features = ["tokio1"] } -async-trait = "^0.1.57" -compact_jwt = "^0.2.3" -futures-util = "^0.3.21" -http-types = "^2.12.0" -kanidm = { path = "../idm" } -kanidm_proto = { path = "../../kanidm_proto" } -ldap3_proto = "^0.2.3" -libc = "^0.2.127" -openssl = "^0.10.41" -regex = "1.5.6" -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -sketching = { path = "../../sketching" } -tide = "^0.16.0" +async-std = { workspace = true, features = ["tokio1"] } +async-trait.workspace = true +compact_jwt.workspace = true +futures-util.workspace = true +http-types.workspace = true +kanidm.workspace = true +kanidm_proto.workspace = true +ldap3_proto.workspace = true +libc.workspace = true +openssl.workspace = true +regex.workspace = true +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +sketching.workspace = true +tide.workspace = true # I tried including brotli and it didn't work, including "default" pulls a mime-type list from the internet on build -tide-compress = { version = "0.10.6", default-features = false, features = [ "deflate", "gzip", "regex-check" ] } -tide-openssl = "^0.1.1" -tokio = { version = "^1.21.1", features = ["net", "sync", "io-util", "macros"] } -tokio-openssl = "^0.6.3" -tokio-util = { version = "^0.7.4", features = ["codec"] } -tracing = { version = "^0.1.35", features = ["attributes"] } -uuid = { version = "^1.1.2", features = ["serde", "v4" ] } +tide-compress = { workspace = true, default-features = false, features = [ "deflate", "gzip", "regex-check" ] } +tide-openssl.workspace = true +tokio = { workspace = true, features = ["net", "sync", "io-util", "macros"] } +tokio-openssl.workspace = true +tokio-util = { workspace = true, features = ["codec"] } +tracing = { workspace = true, features = ["attributes"] } +uuid = { workspace = true, features = ["serde", "v4" ] } [build-dependencies] -profiles = { path = "../../profiles" } +profiles.workspace = true [dev-dependencies] -kanidm_client = { path = "../../kanidm_client" } -futures = "^0.3.21" +kanidm_client.workspace = true +futures.workspace = true webauthn-authenticator-rs.workspace = true -oauth2_ext = { package = "oauth2", version = "^4.1.0", default-features = false } -base64 = "^0.13.0" +oauth2_ext = { workspace = true, default-features = false } -url = { version = "^2.3.1", features = ["serde"] } -reqwest = { version = "0.11.11", features=["cookies", "json", "native-tls"] } +url = { workspace = true, features = ["serde"] } +reqwest = { workspace = true, features=["cookies", "json", "native-tls"] } diff --git a/kanidmd/score/src/https/manifest.rs b/kanidmd/score/src/https/manifest.rs index c76b348b6..d1634165d 100644 --- a/kanidmd/score/src/https/manifest.rs +++ b/kanidmd/score/src/https/manifest.rs @@ -1,7 +1,8 @@ +use serde::{Deserialize, Serialize}; + ///! Builds a Progressive Web App Manifest page. // Thanks to the webmanifest crate for a lot of this code use crate::https::{AppState, RequestExtensions}; -use serde::{Deserialize, Serialize}; /// The MIME type for `.webmanifest` files. const MIME_TYPE_MANIFEST: &str = "application/manifest+json;charset=utf-8"; diff --git a/kanidmd/score/src/https/middleware.rs b/kanidmd/score/src/https/middleware.rs index fc163768a..27c3b5114 100644 --- a/kanidmd/score/src/https/middleware.rs +++ b/kanidmd/score/src/https/middleware.rs @@ -1,6 +1,7 @@ +use regex::Regex; + ///! Custom tide middleware for Kanidm use crate::https::JavaScriptFile; -use regex::Regex; /// This is for the tide_compression middleware so that we only compress certain content types. /// diff --git a/kanidmd/score/src/https/mod.rs b/kanidmd/score/src/https/mod.rs index bc935bb03..c4a831220 100644 --- a/kanidmd/score/src/https/mod.rs +++ b/kanidmd/score/src/https/mod.rs @@ -4,11 +4,9 @@ mod oauth2; mod routemaps; mod v1; -use self::manifest::manifest; -use self::middleware::*; -use self::oauth2::*; -use self::routemaps::{RouteMap, RouteMaps}; -use self::v1::*; +use std::fs::canonicalize; +use std::path::PathBuf; +use std::str::FromStr; use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator}; use kanidm::actors::v1_read::QueryServerReadV1; @@ -17,14 +15,17 @@ use kanidm::config::{ServerRole, TlsConfiguration}; use kanidm::prelude::*; use kanidm::status::StatusActor; use serde::Serialize; -use std::fs::canonicalize; -use std::path::PathBuf; -use std::str::FromStr; use tide_compress::CompressMiddleware; use tide_openssl::TlsListener; use tracing::{error, info}; use uuid::Uuid; +use self::manifest::manifest; +use self::middleware::*; +use self::oauth2::*; +use self::routemaps::{RouteMap, RouteMaps}; +use self::v1::*; + #[derive(Clone)] pub struct JavaScriptFile { // Relative to the pkg/ dir diff --git a/kanidmd/score/src/https/oauth2.rs b/kanidmd/score/src/https/oauth2.rs index 85270b4ff..e40d65524 100644 --- a/kanidmd/score/src/https/oauth2.rs +++ b/kanidmd/score/src/https/oauth2.rs @@ -1,5 +1,3 @@ -use super::v1::{json_rest_event_get, json_rest_event_post}; -use super::{to_tide_response, AppState, RequestExtensions}; use kanidm::idm::oauth2::{ AccessTokenIntrospectRequest, AccessTokenRequest, AuthorisationRequest, AuthorisePermitSuccess, AuthoriseResponse, ErrorResponse, Oauth2Error, @@ -9,6 +7,9 @@ use kanidm_proto::oauth2::AuthorisationResponse; use kanidm_proto::v1::Entry as ProtoEntry; use serde::{Deserialize, Serialize}; +use super::v1::{json_rest_event_get, json_rest_event_post}; +use super::{to_tide_response, AppState, RequestExtensions}; + // == Oauth2 Configuration Endpoints == pub async fn oauth2_get(req: tide::Request) -> tide::Result { diff --git a/kanidmd/score/src/https/routemaps.rs b/kanidmd/score/src/https/routemaps.rs index cace10f13..8befd96c5 100644 --- a/kanidmd/score/src/https/routemaps.rs +++ b/kanidmd/score/src/https/routemaps.rs @@ -1,11 +1,11 @@ -use crate::https::AppState; ///! Route-mapping magic for tide /// /// Instead of adding routes with (for example) the .post method you add them with .mapped_post, pasing an instance of [RouteMap] and it'll do the rest... -/// use serde::{Deserialize, Serialize}; use tide::{Endpoint, Route}; +use crate::https::AppState; + // Extends the tide::Route for RouteMaps, this would really be nice if it was generic :( pub trait RouteMaps { fn mapped_method( @@ -43,21 +43,27 @@ impl RouteMaps for Route<'_, AppState> { routemap.routelist.push(RouteInfo { path, method }); self.method(method, ep) } + fn mapped_delete(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Delete, ep) } + fn mapped_get(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Get, ep) } + fn mapped_patch(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Patch, ep) } + fn mapped_post(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Post, ep) } + fn mapped_put(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Put, ep) } + fn mapped_update(&mut self, routemap: &mut RouteMap, ep: impl Endpoint) -> &mut Self { self.mapped_method(routemap, http_types::Method::Update, ep) } @@ -88,6 +94,7 @@ impl RouteMap { pub fn do_map(&self) -> String { serde_json::to_string_pretty(self).unwrap() } + // Inject the route for the routemap endpoint pub fn push_self(&mut self, path: String, method: http_types::Method) { self.routelist.push(RouteInfo { path, method }); diff --git a/kanidmd/score/src/https/v1.rs b/kanidmd/score/src/https/v1.rs index 464d8adba..3dbf6d482 100644 --- a/kanidmd/score/src/https/v1.rs +++ b/kanidmd/score/src/https/v1.rs @@ -1,23 +1,21 @@ +use std::str::FromStr; +use std::time::Duration; + +use async_std::task; +use compact_jwt::Jws; use kanidm::event::AuthResult; use kanidm::filter::{Filter, FilterInvalid}; use kanidm::idm::AuthState; use kanidm::prelude::*; use kanidm::status::StatusRequestEvent; - -use kanidm_proto::v1::Entry as ProtoEntry; use kanidm_proto::v1::{ AccountUnixExtend, ApiTokenGenerate, AuthRequest, AuthResponse, AuthState as ProtoAuthState, - CUIntentToken, CURequest, CUSessionToken, CreateRequest, DeleteRequest, GroupUnixExtend, - ModifyRequest, OperationError, SearchRequest, SingleStringRequest, + CUIntentToken, CURequest, CUSessionToken, CreateRequest, DeleteRequest, Entry as ProtoEntry, + GroupUnixExtend, ModifyRequest, OperationError, SearchRequest, SingleStringRequest, }; +use serde::{Deserialize, Serialize}; use super::{to_tide_response, AppState, RequestExtensions, RouteMap}; -use async_std::task; -use compact_jwt::Jws; -use std::str::FromStr; -use std::time::Duration; - -use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct SessionId { diff --git a/kanidmd/score/src/ldaps.rs b/kanidmd/score/src/ldaps.rs index 823a27b8f..90bb3408f 100644 --- a/kanidmd/score/src/ldaps.rs +++ b/kanidmd/score/src/ldaps.rs @@ -1,18 +1,19 @@ -use kanidm::actors::v1_read::QueryServerReadV1; -use kanidm::ldap::{LdapBoundToken, LdapResponseState}; -use kanidm::prelude::*; -use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder}; +use std::marker::Unpin; +use std::net; use std::pin::Pin; -use tokio_openssl::SslStream; +use std::str::FromStr; use futures_util::sink::SinkExt; use futures_util::stream::StreamExt; -use ldap3_proto::{proto::LdapMsg, LdapCodec}; -use std::marker::Unpin; -use std::net; -use std::str::FromStr; +use kanidm::actors::v1_read::QueryServerReadV1; +use kanidm::ldap::{LdapBoundToken, LdapResponseState}; +use kanidm::prelude::*; +use ldap3_proto::proto::LdapMsg; +use ldap3_proto::LdapCodec; +use openssl::ssl::{Ssl, SslAcceptor, SslAcceptorBuilder}; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpListener; +use tokio_openssl::SslStream; use tokio_util::codec::{FramedRead, FramedWrite}; struct LdapSession { diff --git a/kanidmd/score/src/lib.rs b/kanidmd/score/src/lib.rs index c521864fe..fe381eb47 100644 --- a/kanidmd/score/src/lib.rs +++ b/kanidmd/score/src/lib.rs @@ -29,12 +29,10 @@ pub mod https; mod ldaps; // use crossbeam::channel::unbounded; +use std::sync::Arc; + use async_std::task; use compact_jwt::JwsSigner; -use kanidm::prelude::*; -#[cfg(not(target_family = "windows"))] -use libc::umask; - use kanidm::actors::v1_read::QueryServerReadV1; use kanidm::actors::v1_write::QueryServerWriteV1; use kanidm::be::{Backend, BackendConfig, BackendTransaction, FsType}; @@ -43,13 +41,14 @@ use kanidm::crypto::setup_tls; use kanidm::idm::server::{IdmServer, IdmServerDelayed}; use kanidm::interval::IntervalActor; use kanidm::ldap::LdapServer; +use kanidm::prelude::*; use kanidm::schema::Schema; use kanidm::status::StatusActor; use kanidm::utils::{duration_from_epoch_now, touch_file_or_quit}; use kanidm_proto::messages::{AccountChangeMessage, MessageStatus}; use kanidm_proto::v1::OperationError; - -use std::sync::Arc; +#[cfg(not(target_family = "windows"))] +use libc::umask; // === internal setup helpers diff --git a/kanidmd/score/tests/https_middleware.rs b/kanidmd/score/tests/https_middleware.rs index d81f0f5ad..708015734 100644 --- a/kanidmd/score/tests/https_middleware.rs +++ b/kanidmd/score/tests/https_middleware.rs @@ -1,14 +1,12 @@ use std::sync::atomic::Ordering; mod common; -use crate::common::{ADMIN_TEST_PASSWORD, ADMIN_TEST_USER, PORT_ALLOC}; - use kanidm::audit::LogLevel; use kanidm::config::{Configuration, IntegrationTestConfig, ServerRole}; use score::create_server_core; use tokio::task; -use crate::common::is_free_port; +use crate::common::{is_free_port, ADMIN_TEST_PASSWORD, ADMIN_TEST_USER, PORT_ALLOC}; #[tokio::test] async fn test_https_middleware_headers() { diff --git a/kanidmd/score/tests/oauth2_test.rs b/kanidmd/score/tests/oauth2_test.rs index 88eb322fc..f43b3f305 100644 --- a/kanidmd/score/tests/oauth2_test.rs +++ b/kanidmd/score/tests/oauth2_test.rs @@ -1,6 +1,8 @@ #![deny(warnings)] mod common; -use crate::common::{setup_async_test, ADMIN_TEST_PASSWORD}; +use std::collections::HashMap; +use std::convert::TryFrom; +use std::str::FromStr; use compact_jwt::{JwkKeySet, JwsValidator, OidcToken, OidcUnverified}; use kanidm_proto::oauth2::{ @@ -8,11 +10,10 @@ use kanidm_proto::oauth2::{ AccessTokenResponse, AuthorisationResponse, OidcDiscoveryResponse, }; use oauth2_ext::PkceCodeChallenge; -use std::collections::HashMap; -use std::convert::TryFrom; -use std::str::FromStr; use url::Url; +use crate::common::{setup_async_test, ADMIN_TEST_PASSWORD}; + macro_rules! assert_no_cache { ($response:expr) => {{ // Check we have correct nocache headers. diff --git a/kanidmd/score/tests/proto_v1_test.rs b/kanidmd/score/tests/proto_v1_test.rs index f9c8e8f88..8ef10f64f 100644 --- a/kanidmd/score/tests/proto_v1_test.rs +++ b/kanidmd/score/tests/proto_v1_test.rs @@ -1,19 +1,20 @@ #![deny(warnings)] use std::time::SystemTime; -use tracing::debug; - use kanidm::credential::totp::Totp; use kanidm_proto::v1::{ ApiToken, CURegState, CredentialDetailType, Entry, Filter, Modify, ModifyList, }; +use tracing::debug; mod common; -use crate::common::{setup_async_test, ADMIN_TEST_PASSWORD}; -use compact_jwt::JwsUnverified; use std::str::FromStr; -use webauthn_authenticator_rs::{softpasskey::SoftPasskey, WebauthnAuthenticator}; +use compact_jwt::JwsUnverified; +use webauthn_authenticator_rs::softpasskey::SoftPasskey; +use webauthn_authenticator_rs::WebauthnAuthenticator; + +use crate::common::{setup_async_test, ADMIN_TEST_PASSWORD}; const UNIX_TEST_PASSWORD: &str = "unix test user password"; diff --git a/kanidmd_web_ui/Cargo.toml b/kanidmd_web_ui/Cargo.toml index 7acb584a0..9a4845e34 100644 --- a/kanidmd_web_ui/Cargo.toml +++ b/kanidmd_web_ui/Cargo.toml @@ -1,47 +1,43 @@ [package] name = "kanidmd_web_ui" -version = "1.1.0-alpha.9" -authors = [ - "William Brown ", - "James Hodgkinson ", - ] -rust-version = "1.64" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Server Web User Interface" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +version.workspace = true +authors.workspace = true +rust-version.workspace = true +edition.workspace = true +license.workspace = true +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"] [dependencies] -compact_jwt = { version = "^0.2.3", default-features = false, features = ["unsafe_release_without_verify"] } -# compact_jwt = { path = "../../compact_jwt" , default-features = false, features = ["unsafe_release_without_verify"] } -gloo = "^0.8.0" -gloo-net = "0.2.4" -js-sys = "^0.3.58" -kanidm_proto = { path = "../kanidm_proto", features = ["wasm"] } -qrcode = { version = "^0.12.0", default-features = false, features = ["svg"] } -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -serde-wasm-bindgen = "0.4" -uuid = "^1.1.2" -wasm-bindgen = { version = "^0.2.81" } -wasm-bindgen-futures = { version = "^0.4.30" } -wasm-bindgen-test = "0.3.33" -yew = "^0.19.3" -yew-agent = "^0.1.0" -yew-router = "^0.16.0" +compact_jwt = { workspace = true, default-features = false, features = ["unsafe_release_without_verify"] } +gloo.workspace = true +gloo-net.workspace = true +js-sys.workspace = true +kanidm_proto = { workspace = true, features = ["wasm"] } +qrcode = { workspace = true, default-features = false, features = ["svg"] } +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +serde-wasm-bindgen.workspace = true +uuid.workspace = true +wasm-bindgen.workspace = true +wasm-bindgen-futures.workspace = true +wasm-bindgen-test.workspace = true +yew.workspace = true +yew-agent.workspace = true +yew-router.workspace = true [dependencies.web-sys] -version = "^0.3.60" +workspace = true features = [ "AuthenticationExtensionsClientOutputs", "AuthenticatorResponse", diff --git a/kanidmd_web_ui/pkg/kanidmd_web_ui.js b/kanidmd_web_ui/pkg/kanidmd_web_ui.js deleted file mode 100644 index 36fc947f2..000000000 --- a/kanidmd_web_ui/pkg/kanidmd_web_ui.js +++ /dev/null @@ -1,1093 +0,0 @@ -import { modal_hide_by_id } from '/pkg/wasmloader.js'; - -let wasm; - -const heap = new Array(32).fill(undefined); - -heap.push(undefined, null, true, false); - -function getObject(idx) { return heap[idx]; } - -function isLikeNone(x) { - return x === undefined || x === null; -} - -let cachedFloat64Memory0 = new Float64Array(); - -function getFloat64Memory0() { - if (cachedFloat64Memory0.byteLength === 0) { - cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); - } - return cachedFloat64Memory0; -} - -let cachedInt32Memory0 = new Int32Array(); - -function getInt32Memory0() { - if (cachedInt32Memory0.byteLength === 0) { - cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); - } - return cachedInt32Memory0; -} - -let WASM_VECTOR_LEN = 0; - -let cachedUint8Memory0 = new Uint8Array(); - -function getUint8Memory0() { - if (cachedUint8Memory0.byteLength === 0) { - cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); - } - return cachedUint8Memory0; -} - -const cachedTextEncoder = new TextEncoder('utf-8'); - -const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' - ? function (arg, view) { - return cachedTextEncoder.encodeInto(arg, view); -} - : function (arg, view) { - const buf = cachedTextEncoder.encode(arg); - view.set(buf); - return { - read: arg.length, - written: buf.length - }; -}); - -function passStringToWasm0(arg, malloc, realloc) { - - if (realloc === undefined) { - const buf = cachedTextEncoder.encode(arg); - const ptr = malloc(buf.length); - getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); - WASM_VECTOR_LEN = buf.length; - return ptr; - } - - let len = arg.length; - let ptr = malloc(len); - - const mem = getUint8Memory0(); - - let offset = 0; - - for (; offset < len; offset++) { - const code = arg.charCodeAt(offset); - if (code > 0x7F) break; - mem[ptr + offset] = code; - } - - if (offset !== len) { - if (offset !== 0) { - arg = arg.slice(offset); - } - ptr = realloc(ptr, len, len = offset + arg.length * 3); - const view = getUint8Memory0().subarray(ptr + offset, ptr + len); - const ret = encodeString(arg, view); - - offset += ret.written; - } - - WASM_VECTOR_LEN = offset; - return ptr; -} - -let heap_next = heap.length; - -function addHeapObject(obj) { - if (heap_next === heap.length) heap.push(heap.length + 1); - const idx = heap_next; - heap_next = heap[idx]; - - heap[idx] = obj; - return idx; -} - -const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); - -cachedTextDecoder.decode(); - -function getStringFromWasm0(ptr, len) { - return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); -} - -function dropObject(idx) { - if (idx < 36) return; - heap[idx] = heap_next; - heap_next = idx; -} - -function takeObject(idx) { - const ret = getObject(idx); - dropObject(idx); - return ret; -} - -function debugString(val) { - // primitive types - const type = typeof val; - if (type == 'number' || type == 'boolean' || val == null) { - return `${val}`; - } - if (type == 'string') { - return `"${val}"`; - } - if (type == 'symbol') { - const description = val.description; - if (description == null) { - return 'Symbol'; - } else { - return `Symbol(${description})`; - } - } - if (type == 'function') { - const name = val.name; - if (typeof name == 'string' && name.length > 0) { - return `Function(${name})`; - } else { - return 'Function'; - } - } - // objects - if (Array.isArray(val)) { - const length = val.length; - let debug = '['; - if (length > 0) { - debug += debugString(val[0]); - } - for(let i = 1; i < length; i++) { - debug += ', ' + debugString(val[i]); - } - debug += ']'; - return debug; - } - // Test for built-in - const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); - let className; - if (builtInMatches.length > 1) { - className = builtInMatches[1]; - } else { - // Failed to match the standard '[object ClassName]' - return toString.call(val); - } - if (className == 'Object') { - // we're a user defined class or Object - // JSON.stringify avoids problems with cycles, and is generally much - // easier than looping through ownProperties of `val`. - try { - return 'Object(' + JSON.stringify(val) + ')'; - } catch (_) { - return 'Object'; - } - } - // errors - if (val instanceof Error) { - return `${val.name}: ${val.message}\n${val.stack}`; - } - // TODO we could test for more things here, like `Set`s and `Map`s. - return className; -} - -function makeMutClosure(arg0, arg1, dtor, f) { - const state = { a: arg0, b: arg1, cnt: 1, dtor }; - const real = (...args) => { - // First up with a closure we increment the internal reference - // count. This ensures that the Rust closure environment won't - // be deallocated while we're invoking it. - state.cnt++; - const a = state.a; - state.a = 0; - try { - return f(a, state.b, ...args); - } finally { - if (--state.cnt === 0) { - wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); - - } else { - state.a = a; - } - } - }; - real.original = state; - - return real; -} - -let stack_pointer = 32; - -function addBorrowedObject(obj) { - if (stack_pointer == 1) throw new Error('out of js stack'); - heap[--stack_pointer] = obj; - return stack_pointer; -} -function __wbg_adapter_36(arg0, arg1, arg2) { - try { - wasm._dyn_core__ops__function__FnMut___A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hbcc7dfc6c2687f89(arg0, arg1, addBorrowedObject(arg2)); - } finally { - heap[stack_pointer++] = undefined; - } -} - -function makeClosure(arg0, arg1, dtor, f) { - const state = { a: arg0, b: arg1, cnt: 1, dtor }; - const real = (...args) => { - // First up with a closure we increment the internal reference - // count. This ensures that the Rust closure environment won't - // be deallocated while we're invoking it. - state.cnt++; - try { - return f(state.a, state.b, ...args); - } finally { - if (--state.cnt === 0) { - wasm.__wbindgen_export_2.get(state.dtor)(state.a, state.b); - state.a = 0; - - } - } - }; - real.original = state; - - return real; -} -function __wbg_adapter_39(arg0, arg1, arg2) { - wasm._dyn_core__ops__function__Fn__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h6d98df24b306b11b(arg0, arg1, addHeapObject(arg2)); -} - -function __wbg_adapter_42(arg0, arg1, arg2) { - wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h93ba8e63e7e4f60b(arg0, arg1, addHeapObject(arg2)); -} - -/** -*/ -export function run_app() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.run_app(retptr); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -let cachedUint32Memory0 = new Uint32Array(); - -function getUint32Memory0() { - if (cachedUint32Memory0.byteLength === 0) { - cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer); - } - return cachedUint32Memory0; -} - -function getArrayJsValueFromWasm0(ptr, len) { - const mem = getUint32Memory0(); - const slice = mem.subarray(ptr / 4, ptr / 4 + len); - const result = []; - for (let i = 0; i < slice.length; i++) { - result.push(takeObject(slice[i])); - } - return result; -} - -function handleError(f, args) { - try { - return f.apply(this, args); - } catch (e) { - wasm.__wbindgen_exn_store(addHeapObject(e)); - } -} - -async function load(module, imports) { - if (typeof Response === 'function' && module instanceof Response) { - if (typeof WebAssembly.instantiateStreaming === 'function') { - try { - return await WebAssembly.instantiateStreaming(module, imports); - - } catch (e) { - if (module.headers.get('Content-Type') != 'application/wasm') { - console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); - - } else { - throw e; - } - } - } - - const bytes = await module.arrayBuffer(); - return await WebAssembly.instantiate(bytes, imports); - - } else { - const instance = await WebAssembly.instantiate(module, imports); - - if (instance instanceof WebAssembly.Instance) { - return { instance, module }; - - } else { - return instance; - } - } -} - -function getImports() { - const imports = {}; - imports.wbg = {}; - imports.wbg.__wbindgen_is_bigint = function(arg0) { - const ret = typeof(getObject(arg0)) === 'bigint'; - return ret; - }; - imports.wbg.__wbindgen_is_undefined = function(arg0) { - const ret = getObject(arg0) === undefined; - return ret; - }; - imports.wbg.__wbindgen_number_get = function(arg0, arg1) { - const obj = getObject(arg1); - const ret = typeof(obj) === 'number' ? obj : undefined; - getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; - getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); - }; - imports.wbg.__wbindgen_boolean_get = function(arg0) { - const v = getObject(arg0); - const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; - return ret; - }; - imports.wbg.__wbindgen_string_get = function(arg0, arg1) { - const obj = getObject(arg1); - const ret = typeof(obj) === 'string' ? obj : undefined; - var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - var len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbindgen_is_object = function(arg0) { - const val = getObject(arg0); - const ret = typeof(val) === 'object' && val !== null; - return ret; - }; - imports.wbg.__wbindgen_is_string = function(arg0) { - const ret = typeof(getObject(arg0)) === 'string'; - return ret; - }; - imports.wbg.__wbindgen_object_clone_ref = function(arg0) { - const ret = getObject(arg0); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_string_new = function(arg0, arg1) { - const ret = getStringFromWasm0(arg0, arg1); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_object_drop_ref = function(arg0) { - takeObject(arg0); - }; - imports.wbg.__wbindgen_cb_drop = function(arg0) { - const obj = takeObject(arg0).original; - if (obj.cnt-- == 1) { - obj.a = 0; - return true; - } - const ret = false; - return ret; - }; - imports.wbg.__wbg_modalhidebyid_3090e1f0ff737387 = function(arg0, arg1) { - modal_hide_by_id(getStringFromWasm0(arg0, arg1)); - }; - imports.wbg.__wbg_BigInt_d0c7d465bfa30d3b = function(arg0) { - const ret = BigInt(arg0); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_number_new = function(arg0) { - const ret = arg0; - return addHeapObject(ret); - }; - imports.wbg.__wbg_BigInt_1fab4952b6c4a499 = function(arg0) { - const ret = BigInt(BigInt.asUintN(64, arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_is_null = function(arg0) { - const ret = getObject(arg0) === null; - return ret; - }; - imports.wbg.__wbg_BigInt_06819bca5a5bedef = function(arg0) { - const ret = BigInt(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_BigInt_67359e71cae1c6c9 = function(arg0) { - const ret = BigInt(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_get_2268d91a19a98b92 = function(arg0, arg1) { - const ret = getObject(arg0)[takeObject(arg1)]; - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_c943d600fa71e4dd = function(arg0, arg1, arg2) { - getObject(arg0)[takeObject(arg1)] = takeObject(arg2); - }; - imports.wbg.__wbg_new_abda76e883ba8a5f = function() { - const ret = new Error(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { - const ret = getObject(arg1).stack; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { - try { - console.error(getStringFromWasm0(arg0, arg1)); - } finally { - wasm.__wbindgen_free(arg0, arg1); - } - }; - imports.wbg.__wbg_debug_783a3d4910bc24c7 = function(arg0, arg1) { - var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); - wasm.__wbindgen_free(arg0, arg1 * 4); - console.debug(...v0); - }; - imports.wbg.__wbg_error_71d6845bf00a930f = function(arg0, arg1) { - var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); - wasm.__wbindgen_free(arg0, arg1 * 4); - console.error(...v0); - }; - imports.wbg.__wbg_log_1f7f93998ab961f7 = function(arg0, arg1) { - var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); - wasm.__wbindgen_free(arg0, arg1 * 4); - console.log(...v0); - }; - imports.wbg.__wbg_warn_0b90a269a514ae1d = function(arg0, arg1) { - var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice(); - wasm.__wbindgen_free(arg0, arg1 * 4); - console.warn(...v0); - }; - imports.wbg.__wbg_instanceof_Window_acc97ff9f5d2c7b4 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Window; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_document_3ead31dbcad65886 = function(arg0) { - const ret = getObject(arg0).document; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_location_8cc8ccf27e342c0a = function(arg0) { - const ret = getObject(arg0).location; - return addHeapObject(ret); - }; - imports.wbg.__wbg_history_2a104346a1208269 = function() { return handleError(function (arg0) { - const ret = getObject(arg0).history; - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_navigator_d1dcf282b97e2495 = function(arg0) { - const ret = getObject(arg0).navigator; - return addHeapObject(ret); - }; - imports.wbg.__wbg_localStorage_753b6d15a844c3dc = function() { return handleError(function (arg0) { - const ret = getObject(arg0).localStorage; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_sessionStorage_4ab60c7f3cb9633b = function() { return handleError(function (arg0) { - const ret = getObject(arg0).sessionStorage; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_fetch_0fe04905cccfc2aa = function(arg0, arg1) { - const ret = getObject(arg0).fetch(getObject(arg1)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_body_3cb4b4042b9a632b = function(arg0) { - const ret = getObject(arg0).body; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_createElement_976dbb84fe1661b5 = function() { return handleError(function (arg0, arg1, arg2) { - const ret = getObject(arg0).createElement(getStringFromWasm0(arg1, arg2)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_createElementNS_1561aca8ee3693c0 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - const ret = getObject(arg0).createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_createTextNode_300f845fab76642f = function(arg0, arg1, arg2) { - const ret = getObject(arg0).createTextNode(getStringFromWasm0(arg1, arg2)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_getElementById_3a708b83e4f034d7 = function(arg0, arg1, arg2) { - const ret = getObject(arg0).getElementById(getStringFromWasm0(arg1, arg2)); - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_querySelector_3628dc2c3319e7e0 = function() { return handleError(function (arg0, arg1, arg2) { - const ret = getObject(arg0).querySelector(getStringFromWasm0(arg1, arg2)); - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_getItem_845e475f85f593e4 = function() { return handleError(function (arg0, arg1, arg2, arg3) { - const ret = getObject(arg1).getItem(getStringFromWasm0(arg2, arg3)); - var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - var len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }, arguments) }; - imports.wbg.__wbg_removeItem_9da69ede4eea3326 = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).removeItem(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_setItem_9c469d634d0c321c = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).setItem(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); - }, arguments) }; - imports.wbg.__wbg_pathname_78a642e573bf8169 = function(arg0, arg1) { - const ret = getObject(arg1).pathname; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_search_afb25c63fe262036 = function(arg0, arg1) { - const ret = getObject(arg1).search; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_setsearch_40007c2a91333011 = function(arg0, arg1, arg2) { - getObject(arg0).search = getStringFromWasm0(arg1, arg2); - }; - imports.wbg.__wbg_new_7d95b89914e4d377 = function() { return handleError(function (arg0, arg1) { - const ret = new URL(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_new_ca4d3a3eca340210 = function() { return handleError(function () { - const ret = new URLSearchParams(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_new_2d0053ee81e4dd2a = function() { return handleError(function () { - const ret = new Headers(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_get_31b57952dfc2c6cc = function() { return handleError(function (arg0, arg1, arg2, arg3) { - const ret = getObject(arg1).get(getStringFromWasm0(arg2, arg3)); - var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - var len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }, arguments) }; - imports.wbg.__wbg_set_992c1d31586b2957 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); - }, arguments) }; - imports.wbg.__wbg_value_ccb32485ee1b3928 = function(arg0, arg1) { - const ret = getObject(arg1).value; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_setvalue_df64bc6794c098f2 = function(arg0, arg1, arg2) { - getObject(arg0).value = getStringFromWasm0(arg1, arg2); - }; - imports.wbg.__wbg_url_1c013f0875e97715 = function(arg0, arg1) { - const ret = getObject(arg1).url; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_headers_85824e993aa739bf = function(arg0) { - const ret = getObject(arg0).headers; - return addHeapObject(ret); - }; - imports.wbg.__wbg_newwithstr_fdce36db91ec5f92 = function() { return handleError(function (arg0, arg1) { - const ret = new Request(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_newwithstrandinit_05d7180788420c40 = function() { return handleError(function (arg0, arg1, arg2) { - const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_add_89a4f3b0846cf0aa = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).add(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_remove_1a26eb5d822902ed = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).remove(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_instanceof_HtmlFormElement_1c489ff7e99e43d3 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof HTMLFormElement; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_instanceof_HtmlInputElement_970e4026de0fccff = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof HTMLInputElement; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_setchecked_f1e1f3e62cdca8e7 = function(arg0, arg1) { - getObject(arg0).checked = arg1 !== 0; - }; - imports.wbg.__wbg_value_b2a620d34c663701 = function(arg0, arg1) { - const ret = getObject(arg1).value; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_setvalue_e5b519cca37d82a7 = function(arg0, arg1, arg2) { - getObject(arg0).value = getStringFromWasm0(arg1, arg2); - }; - imports.wbg.__wbg_instanceof_Element_33bd126d58f2021b = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Element; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_namespaceURI_e19c7be2c60e5b5c = function(arg0, arg1) { - const ret = getObject(arg1).namespaceURI; - var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - var len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_classList_8a97f5e2e1bc3fa9 = function(arg0) { - const ret = getObject(arg0).classList; - return addHeapObject(ret); - }; - imports.wbg.__wbg_setinnerHTML_32081d8a164e6dc4 = function(arg0, arg1, arg2) { - getObject(arg0).innerHTML = getStringFromWasm0(arg1, arg2); - }; - imports.wbg.__wbg_removeAttribute_beaed7727852af78 = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).removeAttribute(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_setAttribute_d8436c14a59ab1af = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); - }, arguments) }; - imports.wbg.__wbg_instanceof_HtmlElement_eff00d16af7bd6e7 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof HTMLElement; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_focus_adfe4cc61e2c09bc = function() { return handleError(function (arg0) { - getObject(arg0).focus(); - }, arguments) }; - imports.wbg.__wbg_create_53c6ddb068a22172 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).create(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_get_da97585bbb5a63bb = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).get(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_href_90ff36b5040e3b76 = function(arg0, arg1) { - const ret = getObject(arg1).href; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbg_credentials_eab5c0bffc3e9cc5 = function(arg0) { - const ret = getObject(arg0).credentials; - return addHeapObject(ret); - }; - imports.wbg.__wbg_getClientExtensionResults_0381c2792f96b9fa = function(arg0) { - const ret = getObject(arg0).getClientExtensionResults(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_instanceof_Event_1009dd203d9055ee = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Event; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_target_bf704b7db7ad1387 = function(arg0) { - const ret = getObject(arg0).target; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_cancelBubble_8c0bdf21c08f1717 = function(arg0) { - const ret = getObject(arg0).cancelBubble; - return ret; - }; - imports.wbg.__wbg_preventDefault_3209279b490de583 = function(arg0) { - getObject(arg0).preventDefault(); - }; - imports.wbg.__wbg_addEventListener_1fc744729ac6dc27 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).addEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), getObject(arg4)); - }, arguments) }; - imports.wbg.__wbg_removeEventListener_b10f1a66647f3aa0 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { - getObject(arg0).removeEventListener(getStringFromWasm0(arg1, arg2), getObject(arg3), arg4 !== 0); - }, arguments) }; - imports.wbg.__wbg_newwithform_6b545e9ddaccc455 = function() { return handleError(function (arg0) { - const ret = new FormData(getObject(arg0)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_get_f1d748260e3dfd1f = function(arg0, arg1, arg2) { - const ret = getObject(arg0).get(getStringFromWasm0(arg1, arg2)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_parentElement_0cffb3ceb0f107bd = function(arg0) { - const ret = getObject(arg0).parentElement; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_lastChild_a2f5ed739809bb31 = function(arg0) { - const ret = getObject(arg0).lastChild; - return isLikeNone(ret) ? 0 : addHeapObject(ret); - }; - imports.wbg.__wbg_setnodeValue_4077cafeefd0725e = function(arg0, arg1, arg2) { - getObject(arg0).nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2); - }; - imports.wbg.__wbg_appendChild_e513ef0e5098dfdd = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).appendChild(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_insertBefore_9f2d2defb9471006 = function() { return handleError(function (arg0, arg1, arg2) { - const ret = getObject(arg0).insertBefore(getObject(arg1), getObject(arg2)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_removeChild_6751e9ca5d9aaf00 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).removeChild(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_pushState_38917fb88b4add30 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4, arg5) { - getObject(arg0).pushState(getObject(arg1), getStringFromWasm0(arg2, arg3), arg4 === 0 ? undefined : getStringFromWasm0(arg4, arg5)); - }, arguments) }; - imports.wbg.__wbg_pathname_4441d4d8fc4aba51 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).pathname; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }, arguments) }; - imports.wbg.__wbg_search_4aac147f005678e5 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg1).search; - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }, arguments) }; - imports.wbg.__wbg_replace_ab0ff56e84982ad2 = function() { return handleError(function (arg0, arg1, arg2) { - getObject(arg0).replace(getStringFromWasm0(arg1, arg2)); - }, arguments) }; - imports.wbg.__wbg_instanceof_Response_eaa426220848a39e = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Response; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_status_c4ef3dd591e63435 = function(arg0) { - const ret = getObject(arg0).status; - return ret; - }; - imports.wbg.__wbg_headers_fd64ad685cf22e5d = function(arg0) { - const ret = getObject(arg0).headers; - return addHeapObject(ret); - }; - imports.wbg.__wbg_json_eb16b12f372e850c = function() { return handleError(function (arg0) { - const ret = getObject(arg0).json(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_text_1169d752cc697903 = function() { return handleError(function (arg0) { - const ret = getObject(arg0).text(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_get_57245cc7d7c7619d = function(arg0, arg1) { - const ret = getObject(arg0)[arg1 >>> 0]; - return addHeapObject(ret); - }; - imports.wbg.__wbg_length_6e3bbe7c8bd4dbd8 = function(arg0) { - const ret = getObject(arg0).length; - return ret; - }; - imports.wbg.__wbg_new_1d9a920c6bfc44a8 = function() { - const ret = new Array(); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_is_function = function(arg0) { - const ret = typeof(getObject(arg0)) === 'function'; - return ret; - }; - imports.wbg.__wbg_newnoargs_b5b063fc6c2f0376 = function(arg0, arg1) { - const ret = new Function(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_new_268f7b7dd3430798 = function() { - const ret = new Map(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_next_579e583d33566a86 = function(arg0) { - const ret = getObject(arg0).next; - return addHeapObject(ret); - }; - imports.wbg.__wbg_next_aaef7c8aa5e212ac = function() { return handleError(function (arg0) { - const ret = getObject(arg0).next(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_done_1b73b0672e15f234 = function(arg0) { - const ret = getObject(arg0).done; - return ret; - }; - imports.wbg.__wbg_value_1ccc36bc03462d71 = function(arg0) { - const ret = getObject(arg0).value; - return addHeapObject(ret); - }; - imports.wbg.__wbg_iterator_6f9d4f28845f426c = function() { - const ret = Symbol.iterator; - return addHeapObject(ret); - }; - imports.wbg.__wbg_get_765201544a2b6869 = function() { return handleError(function (arg0, arg1) { - const ret = Reflect.get(getObject(arg0), getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_call_97ae9d8645dc388b = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).call(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_new_0b9bfdd97583284e = function() { - const ret = new Object(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_self_6d479506f72c6a71 = function() { return handleError(function () { - const ret = self.self; - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_window_f2557cc78490aceb = function() { return handleError(function () { - const ret = window.window; - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_globalThis_7f206bda628d5286 = function() { return handleError(function () { - const ret = globalThis.globalThis; - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_global_ba75c50d1cf384f4 = function() { return handleError(function () { - const ret = global.global; - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_set_a68214f35c417fa9 = function(arg0, arg1, arg2) { - getObject(arg0)[arg1 >>> 0] = takeObject(arg2); - }; - imports.wbg.__wbg_isArray_27c46c67f498e15d = function(arg0) { - const ret = Array.isArray(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_push_740e4b286702d964 = function(arg0, arg1) { - const ret = getObject(arg0).push(getObject(arg1)); - return ret; - }; - imports.wbg.__wbg_instanceof_ArrayBuffer_e5e48f4762c5610b = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof ArrayBuffer; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_instanceof_Error_56b496a10a56de66 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Error; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_new_8d2af00bc1e329ee = function(arg0, arg1) { - const ret = new Error(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_message_fe2af63ccc8985bc = function(arg0) { - const ret = getObject(arg0).message; - return addHeapObject(ret); - }; - imports.wbg.__wbg_name_48eda3ae6aa697ca = function(arg0) { - const ret = getObject(arg0).name; - return addHeapObject(ret); - }; - imports.wbg.__wbg_toString_73c9b562dccf34bd = function(arg0) { - const ret = getObject(arg0).toString(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_933729cf5b66ac11 = function(arg0, arg1, arg2) { - const ret = getObject(arg0).set(getObject(arg1), getObject(arg2)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_isSafeInteger_dfa0593e8d7ac35a = function(arg0) { - const ret = Number.isSafeInteger(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_valueOf_6b6effad03e5c546 = function(arg0) { - const ret = getObject(arg0).valueOf(); - return ret; - }; - imports.wbg.__wbg_entries_65a76a413fc91037 = function(arg0) { - const ret = Object.entries(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_is_40a66842732708e7 = function(arg0, arg1) { - const ret = Object.is(getObject(arg0), getObject(arg1)); - return ret; - }; - imports.wbg.__wbg_toString_7be108a12ef03bc2 = function(arg0) { - const ret = getObject(arg0).toString(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_resolve_99fe17964f31ffc0 = function(arg0) { - const ret = Promise.resolve(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_then_11f7a54d67b4bfad = function(arg0, arg1) { - const ret = getObject(arg0).then(getObject(arg1)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_then_cedad20fbbd9418a = function(arg0, arg1, arg2) { - const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_buffer_3f3d764d4747d564 = function(arg0) { - const ret = getObject(arg0).buffer; - return addHeapObject(ret); - }; - imports.wbg.__wbg_newwithbyteoffsetandlength_d9aa266703cb98be = function(arg0, arg1, arg2) { - const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); - return addHeapObject(ret); - }; - imports.wbg.__wbg_new_8c3f0052272a457a = function(arg0) { - const ret = new Uint8Array(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_83db9690f9353e79 = function(arg0, arg1, arg2) { - getObject(arg0).set(getObject(arg1), arg2 >>> 0); - }; - imports.wbg.__wbg_length_9e1ae1900cb0fbd5 = function(arg0) { - const ret = getObject(arg0).length; - return ret; - }; - imports.wbg.__wbg_instanceof_Uint8Array_971eeda69eb75003 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Uint8Array; - } catch { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_has_8359f114ce042f5a = function() { return handleError(function (arg0, arg1) { - const ret = Reflect.has(getObject(arg0), getObject(arg1)); - return ret; - }, arguments) }; - imports.wbg.__wbg_set_bf3f89b92d5a34bf = function() { return handleError(function (arg0, arg1, arg2) { - const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); - return ret; - }, arguments) }; - imports.wbg.__wbg_stringify_d6471d300ded9b68 = function() { return handleError(function (arg0) { - const ret = JSON.stringify(getObject(arg0)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { - const ret = debugString(getObject(arg1)); - const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len0; - getInt32Memory0()[arg0 / 4 + 0] = ptr0; - }; - imports.wbg.__wbindgen_throw = function(arg0, arg1) { - throw new Error(getStringFromWasm0(arg0, arg1)); - }; - imports.wbg.__wbindgen_memory = function() { - const ret = wasm.memory; - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_closure_wrapper6332 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1615, __wbg_adapter_36); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_closure_wrapper6493 = function(arg0, arg1, arg2) { - const ret = makeClosure(arg0, arg1, 1650, __wbg_adapter_39); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_closure_wrapper6732 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1711, __wbg_adapter_42); - return addHeapObject(ret); - }; - - return imports; -} - -function initMemory(imports, maybe_memory) { - -} - -function finalizeInit(instance, module) { - wasm = instance.exports; - init.__wbindgen_wasm_module = module; - cachedFloat64Memory0 = new Float64Array(); - cachedInt32Memory0 = new Int32Array(); - cachedUint32Memory0 = new Uint32Array(); - cachedUint8Memory0 = new Uint8Array(); - - - return wasm; -} - -function initSync(module) { - const imports = getImports(); - - initMemory(imports); - - if (!(module instanceof WebAssembly.Module)) { - module = new WebAssembly.Module(module); - } - - const instance = new WebAssembly.Instance(module, imports); - - return finalizeInit(instance, module); -} - -async function init(input) { - if (typeof input === 'undefined') { - input = new URL('kanidmd_web_ui_bg.wasm', import.meta.url); - } - const imports = getImports(); - - if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { - input = fetch(input); - } - - initMemory(imports); - - const { instance, module } = await load(await input, imports); - - return finalizeInit(instance, module); -} - -export { initSync } -export default init; diff --git a/kanidmd_web_ui/pkg/kanidmd_web_ui_bg.wasm b/kanidmd_web_ui/pkg/kanidmd_web_ui_bg.wasm deleted file mode 100644 index 6f144858da117621ff3a730270ebcddee23b7651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1599068 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

_#Vs`BL2P);CK$U=tZ%}g@zDJuGv{)Rq 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

{L1D&}E znz#fV69GG}1=QIE#gR#tqZp)^5(6DY$OJh(mC13%!2_U!KR{h5(BLho;lKkv+7!fs zoSX_`*?><@1r>>oGY%bK5ZEopz`Y0RY-nW(T97`0;&n2R#xm%nA5dEq++aj%`$0O3 zAYTi-f*;Nd9V~_%$p-BJfvQeexegjLHe+Ie6y%`75ELQYYoV@(2Rhi)tz4ktS6v1U zN63nL_@QW^MzR`sKm=SBKxz(fdje7Sz&f~4NpPc(1G2_m1JrOd$P(Df4r#3EGH8Gj zDFdjlr3v1#5AquL{1hf|*NOpg7&d4E0JLA11v<|R8f*r2Z$W)c&^{Y*?_OX&AE+@2 zO3dKp01S>2IpA}|IKVA$@Ija?imafc8A0@;P7@O=wu$UoV-gN>SP`iCzp`n<-s91fEr&aT}u|=vXFjBkQ7?60^WN zP6cL=uo4TXfe2cI#skW#Y>qtOWisI0tHk2SRHDF|<+z72OMzX1C0l{naR+0T0-L~o zWk}u13{uCS#3-;<4%`P)0~U;(ZALd}ejJ{xrZA}G;1@1$y8o)gI52Of|vcdV15qvrYXsir0 zm`5Y0gAX$#>7(VVM$Alz=iN7B4ksz<7T+Yyr5&Q=D{?A zEMkQzS_l*6Wdxn-20HqU13cmH$N?J0a9jeDmj*3j0Pm~?74_gF-xh+p%iz{C5e;*2 z-B0&3M0bFCn2>e|xOoFPjvKVFRD+2_fE_f%2yUS$fmeKhk6mK{t=s^$^FY%sEZ`k{ zSJgqwEEz$KbWnpAeBvAO^%&rJZ^kUpR5SLgFhGl_?ts?*fsQc&SFxZz47eT12wp#T znu#0K`DEY*+XuSKVmCC|8-NdjfLIMaa?XqiwA~dvd%_M{k`KD;0g{-RL5Z11f!XoO zqf4N3q!gGPFY=l(sel)RD1ayWnL(Xf&@=)^mcV=PAPzIA>kd)|T8<(EZKX4VTH_#- zmcUICg&4#Dx^I9PyiWtv=Kz}rI>;Jq9;kx{?%2atKtT(0(7+rcXtaO@H2VYUm4U`k zbr~SjR2obYj&GW-Fo4sW3}{ptbhb7tc)S%fROQH02#Pz<(R7Z_Kr2PMpz85}{=gO5NunFTg7gPZ_1>nTVCd_jo}#6oT* z2GIT%P^SVk3C2ASlz1R3S|IyFEkOH2Aq^qWUQkB^5Ffq+fzeR|w9XCGiG((|85J17 zEYJ;epw_&jLYBZ?eo&tqdbkQGUn0x{4+_CGC}atolvH8>pUwyg3(x^Epza=I$qEB) z-1n4v?z_y$$O`HrAoXYjW~(~B04;6bEemdNI$8*<(^LW?E@)Mx0!y|Mqa$-k7Dx_Evp6!BK$iuB z><8Uu2I^5UD}XkgfY#W6l*1G#FlB*`$KmI8{4pQA9&5>hgOKs?ZJ=Qj_-Y_<83=YO zc=-;f8=(N&nV zs2c{F9YNZI1MciXZ?|Cv?Z9RMH&{VMENI0fXa_c^j0FpV#t=Y8aAY~MSuudd;vjR; z)N%J?>bM(xDIaX{HaHi8SNvde_daN8aR7RN6=?WjqJSeCsEz>*9gsAQ^?)%;fmz_K z8Ytu*fUZ~rpMwP&j02Tr;Q2Mskylqh(=>RjR+XHK7LCb8A^Uq@(VgqsyxH}K(WI>&y%K$#Yh6Qwl4XC>f z@+>3hh%o5cGpvx)0--z>M@G;(PAHGrkqOjohw_*l!K*W&JVr+r@R*<@v1is`@xhs) z<%6}*JPRGo2d&_MEOldn)_@G4)Z{3TrNjcsKA=H%)TMo(HZW-9610&HH2>hJ0NG{- zM(6u$7bMYM?T)oTy>FYCt zz^0 z6adw=;6=zC0uUIF!{l))RRKm)3fBe0>3 z2XOuG2s+1##ar5uJ6tAc_%1v=sdg*ok?AXZlxgSEyP(I3nglH$;5N*YDDC|gdXgdbfmL%n9DDdPI(xMCS?U~G=wF%(p&PZxblJtJdF=KA(R0;wZq`J z0oq3ZuU!QTf)-f`Y==&dXfRnIFVeEe0(Z&5OSC4aDlmek5E;QjpaohR!26Xzf&#k~ z6qp5;A}!E*0h*Tm09sUrYlYSUsM`-Pf*0t5+zrAYw>Pk%xxIxMG`8}G3DnO8wUQn% zfcP!oixC+GjzecHHJB2VSRDCaE6g4+WI5hp5Ll-PcK%gm1xC;atO6rM5afYBOrQ-{ zU}1p+ARjD1@<9We0+Ztb&=sZ%ERKBG)|kPr00&)F0>9k~vzLt z%LUg!xxfO{S_BD!63_!4ux3Y#EP)14`q_+>eqMlfuE8=f8;R+M#Lz!EK%o!I#L$z* zK}8S$DH1+_GBNmwaZtsAFA^?bmZS^NYk?`?a;FF69B?@V zy5N?NXv~|pp^mE^~MuGZ2-Irj`8H;3+U+vJPUx_4qxky+>Gc4rGIb< z1RCrIrJXep%^k`B!6SQmOzulzp+4|qH^7!8^cctW3GGXfm?uvWxj!sUM- zJoI7ZKdb?Pt^5bKA7G)6wfx7EaS5gzNXCUFoip&HgD>NPQx8ZZQpSa)AFLS{oPh9V zTsON*z1MCCJYp@5@sKIuFYOvL0)nL&19#9hkgh9=S8|cOV2XOHZsXM{F z8E}#M0aAnutboVC15h&p-i&*|nC18YRP2H);hUf;05mVe2oVGoq%R;QI6h#^5_ke? z%WXmO!VOR@0G``XU~$Bomnm-vO@ilTI=6&i#Ss=StU!;28{k;D0I!5WZ88SXG9Pd| z;sv}c#pi{IpyCvy5vehE0U8U?>tUD$kQ;L=K(Tlvic=#ow1Y9wPuj1f5hG((8w0(96rWuJ{Hh*oS;P-;Qch9g))qeo8KO0aO48diaO4C zeV9R@kq5LK5wsJFB@3ctJxB?tC&iNmR{~lCjbzGfkP^_b3rI?sK<5^MmS{sv=>;j_ zL$!zzw0N=sB*822P8C$Cf@Yk!(NDj-4m$6S19aXU=)AMtyDx$EUvhwr1#MLTEm#3x zUPYzT?_kHADr74$fDSMN-&F|;LeQok_Cgj1fmvFh>tVpRN`k~emra6?bp)--gx)f# z$Oyh~((z2gCD1@J?7~S!CNK-UdIPK(6qjU0s~~_AcJEMc%C1$=$|9Yal_Tikc~A9q0{H^ zZOu-b9-Mjp`QGsp{-B+W;CX-WQ3Q^ll|(Y&4JqKAa{}8$Kr7iHoBws7TLn)rK=z)1 zhtWZE_72$!Oqko7Ex-%JAZIH)0?%=RHdli7&TylwM1bsL-VPmGhRpDT0tIwZF|$4+ zn-Ys7H)z2XIDj|=&VY@A?xq4SrvOi%g4Tn9cMd{NM-l*?tN^-eZLtby$1BLKpuG>E z^a5J?0@=C=5&Y&wcRCMS<0dgFw!30_ehvv}rj7*G> zT|Uq-Wzb|208P?^@+tUa4+ZAs;A2IYofJCkm_QfBf|`{)SpxGU!9fKgSdIM;!XLICYd0<9qc!3WtSjUO?MVWkCk6>* zP-hK>L1#-dD6u#eWbrXGGcbaxA5cyQt-k{8$^iI;Vj_fl1(ppaQeN z8V%5bHl%fdpoOapps8I@NdexX2iFYW@eS4tQiHCKTY<$<&<(V$RbZbusFVO#YdfLE z8}*$2lM<)@6eQm1t5DaqKyxAVgd7ef2K0@Bpg;qi%|Y}I!9UQ=f}nkGphdDQkR4(5 zWb8Fr&d9_BN!PG7%b+D~@Cr>POW+su7E1+C;RJFj_^MHXuZoVKrIn!C339?Dc(xT( ztAWxFIKP2+Un+o30fF9e#Ijt0QQ)sED3ghRwoZcf8-Q}P0ci6GDCT9rOW2^t@_?6X zf=Wa1?n~He71#tjIJLsBUxIHIg&u+qJ`)PO(j9UA5_paszIGk#I1Y3096NZ6wnCP` zJ~_}FyDkIt!cNe66bcNEOj)4aXp&Y8pyj>b<(i;&8psnepiApOhp|9c^MZE*tc5lm z;0^_^2D~8&t=vIpwlZljNeFBacLZ0)pyi67Gv<|;9Un|Tz@WekK2VIu5yTRhsseHm z^w?2QSSWzb5LIFZt!)Hta0VSb1InwAS$}ZV06wN(g9&uLmjO zT9JlCIv{3%=eKr(ys#1Og&Cj$e%OErRxg}oWMl*F8-Nye^{`SJ)Exm`BnaBfuLQaT zfCUtzN-UtW?LceoLA3*@<)^?3+G4E4=2)J^r^3L%!ot9U0g#2*n7Kg*zk)8Q0OwRj z1s2E&08HRRGeCVBHpjmVZlG%&nH+^d^$hefWAJ$@W}q{UK;X-wEGNnsK_ah1g8QM=xF~d zEk|JeEk?(EAPF9UcdDR@h|zI9h|3S+f+{j-R}0krSpt#(xr-yq@dC8N23oNVRRX#* zcJ7PApp7`7b6*{&Kx0%nFQ-D;Tptr`rll1a(_M3m-m7fcm(g z^B%w_#)8&OK9W{o5I7Cm6SM)`&>mFo{fg<{PlMUL-!R?#4$Zx*pmmb~bkP^65@is0 zqYhfH1=_K9Oje1N7jzUd3+V1g(7BDEvj#vy;FY!l+vIV{gVZW82)tDXP2gw2bTKP1 z2<%cPpyw4_59rod(8@Cv1_f5`fpF_?$)Vv^(4`j#d54BuL1|znnQq+%ZAn9p@Bx)h zEJ`d2OrXIH&<@MShK7a;1<=rs6iAK%)Eie|0*xy%f-am_U~yy=IIPA4x{VWZ*oFd= zz!f#n@!*V7przkTpuRpM=y*^DN3dDYaTe&k-k{M6e$Wn28R$_@kQN$f-~_($^u{94 zE##mJ#W=DYA1pcu89rKu$Y-!yavbMRIl$n!V9Egof#r${%%D>}z{9tosvf)z1(at% zn_e8jyEmmFyFWk<1Q*tz%Xz>DltC`}1@AHgHT)D91>Qjpkq7Aq`5iRK2iFGLNaP6a znSn2qVF4W+4=U0@#}=tDaL)&I!{O)mft<<=UjC@SB(R4Oa*nG7sM!xvuE6Yg1bRgb zs51yYhn?B+3UA06kt%1Lb%@1&|t03)&z{U=`?W zREKO82JXS@#`#0QjZ=q!8@u6dgdKYfX%K?jfge!YfuN?kD=(wt9#Er90Nnm_JOg4c zfi=n;5p6q;EcE6bGk9nm+(uIb4W2S8QekRFuDwk zjz&-xlcOn=#q4P2&I{@TGlBY<;39z$deImt8#04V=mLp??nmPQZQape5|9R!4gzbq zK-+G3K$H5QO*l;8TiFG^sDhSygSN7P#+xCf5~#=p9RUd*wW3+8RiGQ%CRJc`#NA%~ zh}oX{jMko7LF@K4aV|Xs8a4xU2OtRr)Utj~cbB$t!55$74%3;^7=3^@ba&}1MIv1K z1vB}tRfBR6XxFC(6Xt2v;JgA-06(po8GJAm=n!boycu|ZKIk4vP_6@a%t1{A(5_JE z-7wo389+n$pnMO)pqU)U3G)vyIC2Rrkp)%spwYNlAOZ04uZ&;?^FVwNfhDq_Lsb-* z95;dZd>}sL1la>1J}-z5atG*GDg`FT3m`#Of%A~lra=9A@JT9+ke$&CpxPe91|84t z2s&B?+DLI^Mm~uR%m$xSwHX@J(7|`mpu7U3Ba6TXbx^WL?4jiam5z*%?l*KVEhtVv z!2Rk8#Q2rGfkG64j*#0RRqRk9RptazeC%EC9tnmcw}W zA)n&|R(<630nlL!$(LjrpjNFH>sGA|^s4}tjLlmZHDXx2Of5@Z!P zN2RQZ&EXGL9b#|vfovtvDO(JnRUit?u8s@}EYe_igGOFiKv4=B&Vr1*vVqT*22JiU zGCP2ZY0$VU{9I{&UMA249cWk;d}si(0vl*p6_hYp9eF`59MCWdtH1>@@L`xBaZtK; zVSoY{qd|d5+7fh{2>4iI&^2x<;HDc>J-A`0gzd;B$jGVyXc+|PL<|A&;Y$)(N{j-# z!S`uOfKFo(*bTaMOM^*92|PCfy5kshiy4Cg6R6n-n*3kK3MyAYr}}^g>guzQ- z@SNxbns5Z4j{rFi7F5T8+@;F^K0yO?dnfoD8BmylPJ@B(>jrsCL=bY|JV=!iNEXxs z1|0yzq`&~0SLaY*f*hL(J_=j_q=W}_U@S;I*w-3N9I(Y7pgIyXND6C(gQ`JDD}2f% z=s>FDl1Y~s9L*f>fCNBuz$>7Ac84tRP$|d-ilC86(1@wP8qjb7Xn6@}oPo#j%h7`j zj$#6TR6zU3!Bd@}mcB)nBIt5oCeUGPP%krr&W~XbXaG$ZfaZZfr!y~?2Sq$1_$(!e z4D`r+1(2A)1~~I#hDbC9^_f@TXq4&hK@15pfFkQrwd zMGjCS0~G2CEDCH{N}LKDpqT;|1$Iy}RbquFR8L-J1y)Br&=C`?jz<~X6j(t=pcnCi zic?TA4?5mU;4>HKARajPDF+JoI4eIWOgOz@`t0}{2aW^!Z(Efi*O zWO7qtmL|61W(H+MQ0=Y2AkYu0ZW%#i^Bh@@w=W)Ga1;XFhma+(7;$kVc)CttD^vj2 zg^}RBub?!?fHfOpttK=PIX3uHwIxGAH+0y*{#GEu|G z4N?Xg<40V)!=eN_V+TAH4{|N&d>wH41nS9wcHctQYk=>~1Z5-zM#uUr(7lriOpc&C z$9FJ-nwW}A;0VX*%1Hz4${U=-xN^z>yK)9Ik}Fq%F1Q1a$U$2ypu`VatqrS;K(Pcq z=Zyg}&IOvg7FY^C8D0i7@(I19@Wedmp;+JvBjnX)palcq3-~|-b)e=llP0r-68Jtk z76n#2&=7(Gn>l!)7n3Fv510i?6`<2|Ak)mSCJT9PT{48+x_Ah=b@>o->#_lH>jKo- z1aJ)xZX2;EF@Wz0W(5ySfhtwRiSEqM!z(fku`gz4(b@;O;g!lY!d- z3<{tv_3)D%z(-0kfCj`tEkDq4HXK<3JtCmNI`DPCkOTigWBQH~Ia#3c9(-Om=&S?K zwQ67|vVv+V@Kwg(^^u?nGVl^BXl6vd$e1Nd0n0tc;H8d`otO%2kS(F$=@5=AfhQ6Q zY>uGSlDMuczQze!6RE%?Fb8yHF?gRGsQm%Hfdf{-gNFH8K||$fp#rLOz}HoPkG}*JYM@rD0;rGyuWf-}2?APR1a2*Z+QOiQ6S&R- z9Y-gW1sW{?4Q{f4DppX#0MzkDyN?^xst31-z~_g;@1$dLlz~p_FgdooILrW=)BznW z23l$8_~a!>0CZgesPq+hE&^HWfJes-3?1Nx3LYIN&~?DwKNmFT!BVHp;0QVZ7;-Wa zqrh$Ojq9Mb6HMTxrl9MTAcx$6&OZaWQ<09tPhUg`v$6#>oafW|{WYFNP) z2k5YK22ioD03PH}V1*R)pgUY4ERHM%W-tp}8-QE~xxFoy5!}Luj36s8J25CQ)`D6k zP7J|HEYeP(8imn`A!uz)Eoi)2THp_8xEDOv0-EM=VgM~C6i{M<$by{005U>>395%t zfkhgWUm!Vydp5KMq=3ADL12O)C|W^d*5E|NsLQ|!>R5snuLywh7N{q4UJMj#p!JtL zjNG6_GP(?0N=%M_8NfTf9d$sBUq;Z{7Bn5;&K2lB2{R@R$o&P3pj9qNsz42La7vp6 zbsVI52A=s=U=(S)VzX|~z$fv;+0J>`oG+e_3+E3P_3M`;& zgBZBcyE&jzkl3RD5Ac8@89a&!T6aX!QGkCT$E+zZ3Vc%qnF1;Rd9nmPV;=BDi3@*I za1z-p$SF_gF8qP%!uino6GTlSuvZ*ZlfaK(1r6hY#|$7NfuK?qblN7?`=>dw6j%h_ zLytiP7YvY*Md(cq%%DmGTo-~%M$r0d2FTJ?@Kstopi^Z*sRul84!w|h9%$Sdl$}9m z^m?#3fR=26Z)gK$Z-_%VK+DuY=@i^oW#naY1f5+@O_pU><0<3}i-(1ycTi2MR$xW`y?2z_|-FOv*irk%_S$ z++Bc`$DpP0Ph!Hdrggg!e zn%97C0s?7}QeXrRR)KODsQc>JaPuOABWR3;%9J~1NXp-_ZJx)L3fRC zWH~l`xX9r6=Ofeu^BG|~6Ci_b;D#x9+*yeo6u6){0~Q5FPig3G6ws}f3`!iJnwMj_ z5*w)P2|l8QMUfRWBgF!`B!v-tMl)#a2z1LWqreLukQC_pJ!a4ZE-SYJs{-hh9tF^l zGFUfgf`Juus50nuFi=aF2~?_rW}Ug0LNhtdrgMpy&6|cf@Av_2Hg7OEb2_FopAAB1 ze!!d?{W}Pqc>r@-{Ocfe=0Qwn{u+eN{EQjt-v^;HXJBTbe}mAOhh#ApLOdRX&b$L^ zvw`X>#LAMFgV33?FeClRAav$zOlSTWgwC9U>CE4Q(3x{Fo%wMPI&&VTGye}lXWqrk z=}!ltGv{N5=FdUs%zK!j`F0RGa{*>(ei?+$ypI{0-v*&G7h;Cyi$UnjMVQWfKM0-q z05j5Gp*eFsXmmyy=>h>pfkSB5pMcvgpaBQa2swD&4rr+!!JU`Mkp;BGMwbCJ=<3c3xy278`I!N9 zuOBl^@+pW59y|j{z5y*#2i*h+atM>-bMQ7*M^>!2^?~Q9AR{@T83U*jVN*fOkPE;W z9j}1)fO3HLkAfoJvGxC921h{<7il{wXp1BAUQx8|q@ZIQSU`6;JAzIE0-f#v8hiwu z%K%za%L1B^0gpZMWC<+g1`T_I$42IWrX;~5-jD?*pk1U2;DId`CD1|Zj0#MiO03dK zETF@UL1Q(bks0vr9`Fhu(7YK)35x@0M32Q0eBL@}u@h+E2W%E-oDF&nIEV=v$pT#i z4jOPmz6KmTTE^_u)X>mypkWu6ITH)F0xS0f&x|9u{szX3#JxXw@cYgbTC_OMy|~iW)cqc^SaNr_jMpZY3trC0n4y zpDc(Y>p?RJpu+_~vkBmJbcpfJsqo_ppyQpOvwbv}KxrE^!OA4Cn;$fc1u{?sv>+37 zK_N4EP*aH!bQKTi9zW2DJra;nGDgs)nvN1#jw_BGWDsZtts4~qjb$n^fX2Ic99c@T z9ScC)SQ(^2`|&lHIHW-Xc96L#@O%$=wIKI4P(Xnu>>!gZNXZOT^nd~$>sTjfMDPJ< zFFGg%U|s(PS;hl87zMHfju{l-5D$Sym*EBo98d(MsRy8`6n<{UHxmv*hC8=RKFHvB z<<|k|Sm%>p2S8(;bABIyoO`koorQ7LYuEH0c6b zNdy`}1SMnGbPMQqX7JD_c)Dc^BW$__c1ap^SqwDZ!O0Okg$$Z50w1iR0nUVwXk-RY z>w@DN6#GmH;JfJrvcQYh6re+uPW5Q#t_Xlu(LqK~L5pPsvOveLfVbR$LcRu)9zbpe zyAmk@xjjYrzc#-zz416roT0X|?#i5aqujtR7l4m1`FS~n=r4O+bpnyiJ6x-x)f zb|uU~N5gQ##>*KTPaFsBQv}VrgJx7fX$5@x1Nc-8NOFaf^$JX&A#Nqm27Cq&UPdWU zUf^&A-A)b~kY@#L1K?!=U3UhXnBZ0fQ0xfkE*v$*dm!RSjbl?YM?JQ`Q^mZl%(0vu4i3JAksh|=Z6sZc#pxsf7iYy9@ zuHbD_%;03ipun7^#OerLJ`757SxW2>E@)pBD<~U-#_1K<1lDTuf^q>5xCCNTV25OW zuqw!U6a{uD4OI(T<_bFB3A}O;Jc-2Z$N)-xEZj4oEe(NeB{mfX1<<`@Y@qeZ3M`=5 z(O?n~WM=^1+W|Vy0K@>DW5fo!b&1IrG?M|D!C-a--Cqk{^9MeE2y}HKivkNcYI#8i zS+NL!PEB$I&1OJmTp-&_K}7&4%-I}4wH!aUYM>QMpuz<_ zl?Iv~2QSuG3C$7Eh6A$#6X@z&@NO;8R22ibso=zD&ddQSUBG!4vd3BAK0l~+CBe%8 zq9nmJFsL2Ptji!JuuzT%ROmBnFv)IR*8?pFRS}AytBS$l z1o1T}R6yrU3V;p`as=(kWPTqyyPpjwiMqWN;L9e6Z~xgTPWbaAgB>4uim7 z&`Fj8Spr|+=LJn+WMr#%?BiBs1QE{dlmMJi0DKR?o8Qnqk4CsU_ z&_&S-Oxd8Fatch|ybRoqoS>!WjyySzD?rBRGB9w@goc;^xOxD$%s{cA0J_k1E@zotno2G6tlJ zBTHZ>XvY_*=?``yD8+!2+jLMB2J#dG*eXyp0jlV+^glqmideG2X&b%&!2r4x72N*- z70jS28FcO$$f2MuG@zgc@4W(b7C;?Q@MaB=3UJQ@T6duLKl-4RKIoiC(BT9O`iu;U zOpXkS49pIoDkjVEKSP$If#Y?M|M&|*w>o)BE3jlCjzd#mQetsrDN_X1*!-Zhqrd>V zMo5Xtv5^sUiUbqrmZ3$O;8Tbg9sjgkVF2~T6_`O+5@k6uC@^FTyaugbYXCK@xiQ=W zI<;*8-P4O6J~-TCuE69-hv30*4vy%elXJF%IyaDp1`Ft9T2Qf0c>M_|)q~fdKpW7Y zoB&!<0$PItX^>&`#=u%2OFuy63XdRY?Sle?z;Sh0A%N(Tfm)l61bSsi`zfFs(@?gh zfmUEJgEAIq*$yaEDYAjeUl=;Eo8W zs^tJTgcPvtSOcxWRe&dm zE&!FR;GW_%Xbp?JCix5GC~O7rdD37G$Z?=OZeWfI=ngKGECDdb0K_qXa%?~x8z={K zIx-`;4**tpg#jdag#j!JK5z_Fs)0rom>eH~R+%a=S}`OjfHl($$weJapu zTm{hSSD>yAg91}FcubC21JsPma;%3`5QSNe%vqqzX$uvY1P-flgDQOR3Teo&BWU5E z8IuTTqagA<^Nf%{Th9b?rUnyu4;N@DD0GM#($9m$8|Y9V==xdkNEReoz{};~qhpS| zu-(w0Q7?fdBH&gGDDpvv?}E0;L02`xnj}QK@D=DBAka7-Xe5hnE`%-nhTaeX9*j|7 z6abx~3Gx)U*(!iILKCzJ3e@C)9MA+kLX!nFWG5{!1$u-g^iWUmAgn@`;|I{Vn-n;h zKr0!UG?*ZVo@y{L2w<8r9%XU;)LN4CsbTN6_Jh5+DHurnTTJH60fm2ai5FGAM$Q1E{?O9#aBUJ)p4! z1x8StmBo>%BpY(>FDRpf+n*q_Ss-ggL8rEXTXV2R3bY)7oCpJQBty3235Gm@$10#4 z0jfJd)fy;?f%d3^4pD+S9JJ;TTXzH0Uew3}SqWO>4{GI^fle6(jiWdk%o0;(3XKLO$G+!gOCN* zgEv=lI5N7i)PrmTEjk75#3@u_%FTXfiM;u_~}SF}5`$ zy9;asWJHlcfzh!dt1wH65r^7JkZZCW*?qyo-JpPnG{GJJGlJa6qQC@dvx3&7Ls;OR z1P^#gC=d5BP!R_SK_(UOHg(YEPtb-y&}bXsb3s9;f*KKVDk$oaq0B6J&j3 zi7bKtLW(SqIXor-9?(D~D9IxdvWN`#ndEiCBpk5h^qYS7nw(5yKyxdg-ku`363m`^bQZG{E-3ozd?(l!FC%EaF7J3-wkn)2*@f0 z{0@PQnLy8p0~IqMYd|NHgYH!T-MJ$$2{aWa15G#JVMZGz1~VoD(2Ri@lMd*xVhtt> zGbYfX9A|jJr5h-5fo=%Bu@`hR1!!82$x#DR)`5pfKoblgQ#rB(o{NC0CLKucRs-y0 zCdh{U4)lH+sFnxyVVOWZO?V%c0lkw3ntBD5N{;;ApaW~m6d6Dl2!Q&mSxOAh9xSLo zD}dgE1)B@HSQpf2LGHn}6X6nb1v)rn1}Fh5GdRLVMI6BsHj2!UP8z7$3n~^gm{|Cj z7(jEz%)Fp}Hl%(BXFt$ASG3usCNTz{4`u|N()hb*TDIRmtapF@!ex{qwFlR=#lo0CGva!}?`U|X)l;#ltk z8XW{>TNVW-SJ0p}t3a)DYQpHlL1-k^&g1{9u-;y4-xkA(9vGx^iME3Fw-U(%Fx2U zn-ObWK!pzogGPy382Q-Q*x4BvnV8u@>jFSGZ}td)CNmiv=P+go^av<0fHn+*2KYh8 zrl1NwQUeuIXeuA6feZrOVh-wLgYHxo_y{@!(eVfDWRNc~#s?VV4UEB)C2&$4JS}-t zm7AN0#34e9z?uTBKOn_6Y>I~gb&3bvlmL}%u(4>+7J3$QCiwi$H%^!aP`f|?v@`>< zHw!fM44vQkfjqwhz8M2NzXNZqfxEt-u7(N&Xxlt^p%27W3QVBWQ{31EIZcaK*9*zE=-^s}yL|1JptRHPApU6isFhC1$73r!Jme-g9%) z7lu~QE-lbf0tIHLxA!J~o_6NW_9rk=jVuKQ(0*V-2(1XgIYQQSpwaP;ME8MQ`tc$ z`7vavFf8Yu463jpElzOf1hhpL6mg&vkH81kXfW|8fu@-m1^%&v)bW5@Kn$RUDE5IF zP`wLk89K6LDS;bfU?ah2FN2Sxg6IdyBJ_h}6l@(x7PLDYJhuX=szJ6gfL1tx_kJRu zTF+?35CdxDGJsmzpr#>Gs~Kb=Xb=X}qy_C8Cwu}H=)`(RrOnUn*m4m(hXWd(besZW zf4Kmi!yJXRt!F%zJeK(2c#w80-EtM19bpE#u_Lv zIND?>a6&uv3?L&I%$ZCSI3Sk;k?OjcgW7d7=;}JyRzb)JAE?HFVbGF9a;{ZcAclOc zk~Jgv$Zk*}0~v^6h8*^zfP9(K0`U0;433~1Z$R@5m{%x)kGWEYEsupc5k!;g%I%AMPVK@0yF9Kp)z<lz>P}=@JYAeC3PTOphdKx zlkBV*7(r8W44`vv!0Y4~K-UH^LYkJWRt${Xjtt;!{GcIQ6$b9LNC(a?*>!-y5q!cX z{J`1OAR#u;X`%1~XE%a`V5&f~`%I2IKtiDNV0js&96_7MnH&#+guus+GDv~ee}h^D zAR+LfzYJ22pp|7zj(0&qFpcbvkmGZng9Jgx!(usIb|ExiNpH5bvmrOzU^9r2@)EWr z2Yjdl@(dzKn$$L11tWMx6Qq5CITQdo5x~AsiAjMGv`UZBk+lSEEPzpg$&IYhfJ$r@ zBf8`ui~lns*$i4HhcXHQwwavafL$ofROmo0XrL0jR0?#{#R-NiPzw_@RtjshvYG<`tAGNt0xNo>71YoIFPsv%0J`@= zAPdw=1>IN#nhacqy)S2g+Lbc__1+*oIU6t&+NqxLGk6Lb4jF z6sQxY13Ga^fx%G&M1urWKnw-Y5+U%yDM#o{cA&Y?kE+ma8+g%|0I2)s1UW-V0DPzs zC|QB_ZYVgifX0kKBeqIRyr5HVAge1ut6(AXv7n|Z`1U0g25zhg1kp(cClCgt1j0hK zq={V0Tm>D3$_gz~AZHSPyLt$56gA{@-!n6jPN!xD9Tw&IbI}3lfxz%m<{#)VV^C26 zDtK7Isv1EWVMk;`N}0xMup^Keq#R+TOg~5vbf`3zQf3xpf(PCX0`(F=R}p}cp&|=& zJ!Ec?1vJY9UT_MYWdfZ#2I}-FusGG%D6oJo;{@pgO@V=CP(dpjvq5XzL6b_LSsT#0 z2_6M-$B4sm0qi6XP;<=*b#*!9JT7KMP$ACE-39GVW0|X?(>&c=_&gozItftK2EIxM zGA##M-#%9oG@c1MMig`ih%0DX2DHyY#&N~_iwusSgYaas9DlsN$l!S3J+uo1&ZwaM zEDB5l_eDV3MHHDplmO&rITi34ECEi?#0IF347zOxV&;c;7a1HuGdM6aXTZ#y&BzG8 zj2Aj=2rAVg*}9fjt3Ub`7qG1)fSMu!Fi_pnkVN7Wljy zXg>*L9N5*+)$~lDT{R)d45h7G_u z8=Pc7o0vfTIR=5Xpe692>P!bcfE>v%xZ?x2xu(3lj1zyTppi3Bi7z~;{0xe0P-2e$yD%vTaZ4!*2L+_w@0UQyG0<#1_S9yZw1Hgk6 zpgCX%(14485{pxPC^!`NXlQ58Dyw$0!*j}#%N#yFD_tk{KE)U{R75$!w8j9 z$rAW10zRh?Y?Z)KRd8Lx4X#Xfpj6o4^8y_mvO(1;D0v%zM~ScwD}g5S(Q9bXh#J0O zB@4)~5@_8v3+R|WCIuGM8X6SdpxJXXCLc)2$^<$A*^x!y66hXB4sdnN1Ud^@g@Jnt z{CIw7+Zr^P13I3c4RoNjz$MVZ{5M5F2lIpOG-u3G1T7ur0hJkSjywX3!OJ#5TNXe| zBS2Rv^JKv;0Ox?6$`8tUkl7(6MuBzUgZVkY2lIp1_JCs>G^)a3&IBvlxm!U63@D4T zC^73ZZevtp2knAjbgT!j!DY#UtTty*WCN#62hch2piIiH$O7uM52!R# zVg)5b7Dq-mfu*XTy<4Dhv}3YLEWDthNARL{Q1~mbf^Oae2}1800~r81ix48jk)^;2 zx~&gc6tv1mfmL8WE7&YlZJ=ExkTEX>7Emb%cG?HXb~i{oGs2H<0}sE!kLl#d0xt#t zC0uZ=3OdLP)CK^Z%m`it0U2~uU=et$1{#OcU=jcYCwNf-Xq49R26&|oD64|Z0GBo* zXlJ#3058u44^ct}+(3t?f|go>S`iA&0u%Yc^%-~(I4h{D1{qsZf-VMU^ajl)Dlj>| zIdG6c;He0>TP*>q7vM97ETFs17|fXkz$SwB5(&KK2iM{X%!r$eKuL+!k-^=Hfd#rn z2()pD1$v(=C`~aaF$?rEDlvkl6dA!&d!Pkk9w7UnhrxkY5`YsXY-NwY6hQNRLH0JEYzYCQBV-9d z2cq}I3|Upe>;T$;;mXS-1+Fg@7z9p9f>vsBfU0_322N14Fgvn>HcEin{sLJ77sNpQ zQ)XQTF7SvFXq7x8XvsckM!Y@?>^)G`&WWmpksH(m-~q{iDt+!Lh=EdYcLOvW3Od5B zLj)9S;If|?nktxe8AKqC1MSVwU}6y1A`CVRv^xN_Fcvh~%EZeIxlRUjB^7jo887JU zJWz`cG;RutCeS@|;PeElBtSU_x)BlXs`=o)1T^Zv4gr_{K74FU?Cgxp4B(FY3s|QC zv|bV1Yk-{c4hj~?iSIoEU^cAC26I3sW(xEOfGQAB*8);AfDVlR2rAbdvLRgv6KLUY z0Ie2OpnQoeNVyMN@c`>SgVwJ=7ASCJInFo)ZYH;BfO>AA;Q{bzoC3cDL1V>^0$GmB zKnm0aHY$NuJ%G9&XF&p@0w5irm2lvVCE)A7!Bq`-LcsA6NR1v?6SRi|S`i3xE~vVO z(BLTTXM{A;46>C#Q3@)MK>MsfIeR1KaZQUE0fPz?lL6Q_}-09peI8h!^)V}W;zg4gb;fR+k?gGV7t;5fMD zApqKW1Ugtx1T+r>3JcIo7Rc$K#i9bU6$N@V1^z36I+b7p!J9+5r_-Qk0$L?gl8v=n z(m-^#WEyQ8#*D*Z4$y-S33iueG9s;!05x<#3+X`1@j=&wFoK&cimb369V?C=9V@6u z#|rMzf%1h418Bu8Xl*4t&_I_egBC$MCS-y7b)ZEe*qjDFN0|j&2XJ#QN0g=@hk=(i zGAMy6F>nS{U~m-40+oWG9YqRRptWoumJW2w4g+X+GNa?F<|7P_T#j2n6ey8_?sI;9 zn89&>^AS)}P9V#128i3)c!a?bbj-L&mg5PK+8ZDO)HRXFa=Zg#-)I6|s14q7=lJ2> zVFrO;pq1L-oY@6hjtT0RFn|^gg4R2N0#S(>dKU|5EDN;n1#}806KFFmDC>gOLW6oa zplgD8K|`9Lb_jT>G-!5?3DovRox5WOUH|6@T4)X0F%91Pngz0eL4i5D5WKb(Hhl-~ zEeSw&ZGlV$ZJ>a*AL^l#bs|b2L%@sbKotyR;j_Rz@HQ+F@Wx@#f>37ARwyNAQ120R zZz6c25ZoUZ0XH&0%j!TL1#>{xm4LeO{M@iDSfI9oBX|qe71$Q6$PO%mN*J&cqBFmIfW43m#yG z9%2HmE1^6l==bOW-ai zXbUd5?+WT|L)T?73xFoQ8JOx38@$1NT_sQ+1WSS22aYf!AuCS7dp%hcm;@%OK@Z7= zx(G4+1FI)NT>?gdi2|TQDnP--16g$jsp26mP!7;YJ`)2IBd8i-He+G|Rofr~6_^Ds zgO~Y3qmI4cG zmjFmNs5K5+p8$6mXbCdNlPV0{)1ZkTBg|w$2?|u)f{z!5g&E;c`v^WeTm+&U7HZ&e z8&D8~PW%83b7q0U4|McDXhas&o`GLj3=J_@HIC{o*qPCgf&)C`1ggtH9t4L1_U^`I z5s0%P-3@r{4K80m*8@OCgz)w|z$Ge{Jb8F9C{W$s3?l&I4+rLQ}a2bZI)Q5Cvr!?6++Q;J9sr>gDTg@ZB&}DPO7Xwhz!! z3_Q*ZE5$UK86f2>Wb}r}vY(nI*$0$?6Hpw3`ytRc1|N?Dnrucs?H+vu1zeI*(@nQ| zL1_}&Z3mr6!$h8&)`Bu1Xl2t{@c1XV%LZz`3MjA$91sMzt3hJS3M`Pup+J@rGiXGB z1EdH{@MOVsW(%BF1POy%jo_nzB$QZT+7y@tZh>VbAh8KLN(QvLAGCr^fz?qYCrb%D zDgzokU;?cx2e0@8FZF|r5-~9-uyFT-oC|57fjYk61|w+5AJimc1l{conihvFO>po{8FvOpENkE_5&(4ZtEXrUL#3`fQ+@UbQg0^6AsKo`V; zCn`Y4(BN5x)&m+`QDAVaKwe}AYJ`CLz~CW6aPu6pbPrqygI3Ui+zoEvgTfZnCk73g zf%oi#I_sduJGfW{^>9JQoM|vIXfW{zg4UxjIM#py3SP+H-;oFMz7eO5raQDVh#S`RDuv+kWG_bXdx(pnU5e62>&J@sqEJ%O}e3k|1h%=Bczz5_o zIf7^S89<|8poM~of1+uUti;snoiJ64~baXUmhz)cXK+6FJfg`e@ zDG>%xPZ+W%iUD+W4-0sT8{`5O@McrcXxV2~PChh&NOI^xS#*akl*QuEH4^9!T_XW^=xlh1LYj-P5CsJZq$$nF!~kx7 zYBO^Ptda(s4_m_vS{e&FvW1xeYy(q0Xz?9r8igSew1*E=%7ZRjf>fMLpgXKVV{go$ z5n@nZ9lXs{BFpgzXs!vg)`tbsEde5jNSJgYig8fnfC@d(u5U)rI1ywI zE@bosGQ~tEGYLuR$B9b_N9T_o8XZrk(?}0%WbI& zXk->tpn{G_5m*8{xQZKgss`vzIB1o^0UApMmu;Y{kw6C?g6a>@Is|C!BVSqvy0ry# zDjMh{J@9M~_|7_T`h?wd1lq>{8u$TiNd(O%J&^!axZn$vm>t1)zJZpHJA&>=;_d|1 zCy+@NP{@ErAg&05QZ1;25`$Expyg~ljG!(rwC5!N9(Dn(@dwYr!n*E|1Pq>40rfit zmdJo7MnK!u!3*Lb2Lgc(UjsFA!C93V(n$qpA=qX%_>3{=G*y8we6R{bA`7(bA3R|s zlO?d6AAFFK68Q8t&>$8QID3O8h7~}&GzGE*o=JdP3ZUKAka`PLtSXo@f$sidf~~*? z=X}t31rsQr8-SJ_O+*b7M$mx;pgW^MmzRUaF&x3+!sPe?bj*@~z<()FEe0yCK~W7V zUO@9)kd?j+4CV|V$1z(mfaX{kH5nMq83bWI637yGEDqAl0ZLaIOg!Mx8OWAwaN`6t z2nY@v=nyW-w&uaGm$?x%{HP4tvQV}fAOV3HN}#^FBLiqFK7%_qXpx2jvlZyZ zBgmd=M$pMWDh!}8D%fHOP<~<-xGD*1=YeK7!7D*PGkgN`RYA1{s39o;I$RYT=^9KT z0$*f7VxaXyh($1vlSLsDBA{+1DD8k^6}(_h20W51lO=Ehv_~1dEDSWoBmth(fvy@^ z3~d!bswv2BRM6Q?pawi_&{zUKXlw%;GzRS+feais>^s8XDD8M)`w`IjMWCjV;~bFC zntiZ=;~TqF1`Ue#dIa0NAxpk)qdjSFZn2XyxqqoWRJ;1P7H7xx_83Oi&Iw5SI(ED!cAxIqt^1_U?gVclXx zRSC}L;I=eU*#}A$i~^G-K*b+u`UeYj{=k9I*nc6;07XS_7=nj4H$wNVIVeW)E2yC8nQZ?8`Ei*<{V&f1g(UIIqe2W z0Lf_&Kzxt_&>?gROpeb$d~~OM012`PP}gY>cN}1F1i1v}vUK1TsXksD5$`IGGe&#>;VQx z(0RH%S;*qxRsrPHbZ~0|`=RN52v>pY6|k!mm;_ot%NRhXT)-DGKvtiCmMrKph=2|j zQ(zR>3_krFv|<62=RplM1xD!N2FTDItYe}9xwjV7Spi+Y2QDvRy*|)5I;eI5HvxL! z-5=D#a+Ux%i-P*iNXzM%q08wQ6c`1LgATO>7Y@u$4NNFY>6p!#K^Mk?&oc+N;$DL(2y1AJY3Ld1ZYeJR4anU1VE!2kR$0FnZRpZLE9H0 zi%Gy+2f<@Hpc)R;s{k#xf)3Cqfa+&(Csrm)pkEQPjJ;nG)Ds4ES)f+1D1i4_I+{4L zfRD9W3SJN607^R$3|fZvfsv1miJ6&^g#omF&9MWv1o8_bXbB{E0KyT(hVGmeI4Q0G zy4D!9l7$Ya~HCrB8~3 zx=Y{&0%Qn!{E|#2;*m&}zytwB@F)=n=oBMRr4L?X0xE() zzE@!2=XQkNTnQ@CAU9XOf!$o$1MLeyq6(Cvbs1P#92}VxK`VH`t`x`tb#y>|(&NgY z))c5H1ofx{azTX#vp}9AD0zPG?}HZjKVUG29MB5R-niEkzeAZC1221k^tl{QfU<@ZXvhFm zN`TvSpl%JQbO05xpdnSrh4`vY>QBdD3g0A3mkx+oe{%7LzW0WGsaHw#j%gGvZUpVo?jfuEa!do?37 zQ$151V+~}Q2|5Y~8ee2$s&fK+1av2blme4BGlvoz^t9Iphtm|9ofw>;2dw@7&%jit zz%~;m>zvHupuo0)hmjk+e*zT54fV)u(4mTKE)d=Kol`)^c(Wx*gKj$z=+Riq4bIHq z9RUoWt$Uz~5L}3LgX%v>mzhBYR0eWn2|Q5*hbCw_7N`{hsvUVi;~1csBn40pUErlC zNDwr^3Ob4xbmBVb79&tIhCzc#Mu`bB{lf&B(gAI`15bf{SagZOkrRByfa6aPTN=Wi zviK5%qX3vqo?~8-;g}^LOQDWg3u4QH9pHEh#1;axS3yGtwh55Q!STxN=)GKRZyVU`|vV?%>fe{Oz?XtSZcDc3GTS`(mVn=XTZz$+f`nRifC;QEx=u>qT^c2GkZlFpbwhdqO`9)qI@s96je zT80d+LKmKaW^x$7n^!>D5>qMp3RE&cwIdyB13HKfG+x9EuDC&s zlRfO9;sV_3qR=57%@jH06Lcy_g@GG&*$*g|U>FiMNVAEch8t`yu}2vr5Wx4bpv(^v zIgR)jV;b=>Vj7Wj_kpJniE4f$9kcCD0`; zETD-d&;fr+OrQz}d^Qe?5+iu_nbBKXi80fW(H(T^kpg43cM+(W3|<=vN~@sZ0njXy z850Az^99ORm<;Y_kk3I`TY(8QIjzL(_?W>L)Gk+GcI5KpWt4(6ra@<4mN>RdJ;;!y z&%j{K06w7rbQU_Z;}eEFCD5I2IoTis92rrRIWlmA)`Wt_Weq?_^@DnP%nFce1wbo~ zLHDOIaCd_ofs~;^-2)9K1tstpD`?iKK?u|#0Nu_5%E90n66ov~6KL87F{^Y)8e{{= zub}J6nHJ7#0c8Q3L5j+%LfZ_es0I_lMXUCYCFD|caTA#PnrnFG!pBW z!#ExD1<5h{C~`~_v5q-{(=lI>9J8My$21e`n4>ry^A^c52Pkq(3$czlhSM=`kQ{Rm zpJTwo^Ppx7ixPuA<0NJ!W=Ag2BnYT~$Czc!IEfiNGsKevI*5D<6KIYLykZ;Fa%6Gr z0SSOA879zrBW6bl@bV)j(7Yovq!|TH@o+wPVSqpugwN0IcxTo@&#Nfybx`GOH&L$HNGidgf2~t!1U~uDQf?c@C;P?~7<#uEP zw_z0+9XG(Vf*1BX?t^n#96(JG+C~|Q#0{B7VsT_F2Ca0iXJiD8!-596KyC#$Nf;q*N$|coP}5!DG%vV+uEZ#? zn+06zf*SnL%fAFbBWFm5;erNopu=PWSpw@oB{~ae(hJm@hYq7LK;*%zpC&=eG*I^j z(skxQ?a`wj33i0r@d9Wz0NkAy$a1^@>a&2G+LUzXp~rwhdN(jPH85o>5#^>^OpYHI z9XSMGZUP^qPAxYzFoEXN`=H_EkVTx6wsSk`z(yAYvK)0lmt|5q<^c^Phiu5^G4MzX z(eZYee(^@Mn~u`YO`!7)iAqaPnH<5hd$6>0fST$10_fmE?jA%p3))kL?^6c#s6aEk zpi{SCJ7chpByeOYun62y1Woh8Mv6friJ<;D6L_g6rxgPOd?W!p$e_UlntB5dCRj0m z7VJS*9>Pw7hRw(*AX=0V*C20R03D6b2wDLFDuxgZO0a9bLB};f1ESzFEx^@*BTJE^ z3TTxC+%cdw5)ayLY4BV&)m-wEQkT@B&FE`DszOLr2I>idS)g?~;MTH2mcTJ#@Z=O| z1`E=@1uvDuHjfUeK_NrL;FdQiEFd%2u!$+unvp@5VGavqPJ;n5r?G+sbi{)KgX07i z(3}P+!B{cO1uZS;0T16&M`ffOT`%L(U3{3&AHCvN{@MDX@VKX%Ltwroie5y6lz1 zkqJ~~vV+V4UDvi#Qh`;0&6;r=_{tXrMuFMl;JY)ajEM)7D;;^V z1h%Sx(gL`*4jK~_=n{q{64+u3O&m+mL7@fqI%xb4k~qLZ;JgUgHw~IqgKj};Mj2@! z;D{%@gTN6FXzU0?VP?j}0*($AM09}itOgT{zzIkr4xVShr6g$IIikn{2Rf|4LW&1) zk_HuWpkoz4vti(4lc7hnkQ5!4MQ9Tp{U|e8;G$Roc`qN)TMQML1-hXZp@R3AFo4c2 zfbK^Cw`D=25TMaAZ~+6_EeF~mrwE>O2RBAR=^v6)koIAM8_5hz^^TxLiQrC#64L#e zpnGyyq`|BHLFEODz%6x%55VVvfR-oL`GgwhNq10d&bZWQGVdd<^RKF+mRW2d^}PED2x)o#zEP#YF%zSPI_R2cBDp_Q@C_>yJP~ z7|_M;pk^SWzyx;a)g0g}u@yk8zrfp3Kz;HR-wrVdbPI8V7XC3fih<@<83bOlgDzG8 z&-GU@GS!0yycxjvW`h@`flt5z%|f$hIU=oT19uYY-9TG3LG69e^c84M29%s2`z#?# zB|rx|D=-pX;#LhBJO+*Cf|^pG9)=QV9}G{H9wUPisO%IdaTF+ZMHRA7M0WhsGXyFgbfIBw}X3_TAH+!khVWGu;2VgT)QVsHnA0%IXJ ze!D?K%`iIAaF?tH1i1BP6M8V z;{a`kWCH6lW0C<`4&H1b@RJEbQCgUa#3J(?7DD>0dz44qobS| zlZ^tSbo*J?f?rgC@?s6 zHZ(L$U<4mT0g7A(ZdmCBDcKdEB?)9>HYjI<%T$FdXsHFdR}r*G3w$sTR18$u^MI~U z1s$je+H?b2Uj&+bVgl_fas(}7b!6ZMUG4`i`#=uo$P(Bi3EoJi!T>t<6E?WSr~;aY zW)PSl2-@}wTlA&N06Mi%fe~~9B6v0(R6{^+z+}{AU~+uN0N(uwDpx>*VqhmY_D?(j znpZo|59zRjPVRO509xbmmRW&8pcA|R0kpINREUDtj|@~myZ{9Vcx1R6zHb0|oJ|JY ze+Qk5gSd(sy!Q%n6*ULiRn(x01ytaGHj;wQPXd)Jki7p)9Gtf`nL&rauVLE6J7>fccY{@mV)5KwI@e%gzMZKntoQvIG_g!(1~^ zk+W9@mP!Z81wX|H+69|bU@pjFVytJZV*;Jr&J0?Y0&YezC@^N3GB7BzII?hq7E%@| zFnNONHPAtfSy{#mplNsJlC^CLEG?jwXO2uoprhlML8|INiBy3(E6WgB6{`XZH#doS z;V<}Fc5q(!zX5(NJMO&j8=U_^TZ_SGH-Hzofd=svKt~IJ)}x^0g?>=RWCER$Es(9m z3cAx+fmwk$2UO~SZj5qd6zEh_VAW*iP-IhJb!33@7!=td8>%%F7!=sdnIse#oH{`3 zI~gGxn_;INg3BvVSqeIK7MgY0&6yMwSiw_Q{M?Rn)*fU4&DZT&2VGPE-VzFL`+}-> zXuA!3WjXjzO#x752NiJOb^H=&hiZbhID<9@m@$cf&a?nm_>dDdLA#?FLGuPI&`JWd z_?`hout1N~+y~lD4lXhW)ERf+Co2x9Gam86%BTT##-G6v8c)OqMQFSNbwdU|iS8X7 zIpz1@NE`PDM^3o`T68<`Y2%&LpvWov2S*ZpI5?c~40KeGVVB_p)qZ6M9TBQQEnU<9M1SXI5OTl z4C>Vmd|}=2e+v(aKk2IA^T}Tv%b*TFz_u9kag0agBzF>Ae*51L05h; zC@_Hzlmm?#gEokPCL6Or_t%4t&Hx24Xds^zJZ-?Cz$mbqA3Wgz-fleO5cuAA(8R6d z0TBDoe(0r#lR?9DjCD*7jvH2ix9;+SuMAcIZOT?)&}0Gy26Wt;$w{GOxe|i{({j)T zJ~v)QDFsGX1qMeI&mzz)od74dY@K4mA>S=q*?+cOPQ^4``7e^6{qvhe1ccKt}vPEBe5}4mlbUlwcSj^5DBi859^b znII!_;0Z>^=`)}SIq=?X(Eeh`ifix*7~q>7AoI_3xS{k~d9<3Nq-?DLkMn zA{n3u5jrw}j;~~JWXe)t18oa{9%iQiJqr=ExDzt#1R6_)ZZ%-kW#9yz#^T5fTCM;( zcSRse06OiY!Nda!Sw>w3E=McSI4~rwgV#E6K*EU;bo(0U083Eh2%Hy#Pc(HvH`%~v zkHHI8p(_(uK;zM%eW##V9}ouT5d7Cqd{skU@&sLz3O>gZoQyy*30jy9+K2@?Kt};I z-mAjEO?8*NA=f3PjI7WE!2&v2Rf*k^Cr1%<^B=PU3-}5@M@B_9CZsF>m_c3x9RUHJ zpDY30^~a>ZD$uT`2%1&m$x>tm-I)X01Pj_454q`&4LXYr8fRw%g+>{&t&^BhZS7&o z0-s((eQO&*%X2}60q8JM@DM!{h{ph$kY}oA2HnNX1PTS{GzzFz0UbyQnrDUWKm>1E z1_c3Vd4v*ZFD~r*H+{w{;L8xen*>1~22JXNj~53`F@R1`0{Og&C?`x}CejHVOlWSH zzzn)!2EQAK3x+<}Y!a!#&;vTdlm)*NYM2=7!Sg!M*>CXG#Gr~Aw1^123KAT0n#>GJ zpot;SA|}v9IE;=Oprh6iLZI1s&@K;0g)D)i@}OBQNAT4&V8x(Q4+KD`w=sgGSIEO= z)9R2c2knpoU9$sD&0xzx+c>~309nogGKdL0IR!aOmr(&B1lphj-h~RW98?6tEe9_K z0b355QdP(jSSb(NeuF*pGeH(eky8wT#{P8~U~AP$D25uL1tN4i19;T|XzdfDz)>Y| zGab|*U{L~Bl%RQV5SIaTK^VwSpkN2pgW$X3z-PB=FmZrRN|gq!IABs>baiAb0nJN; z?nh++&9#AAnH*UH3)uxuC?f?1Y}r0)i%OS)&yg8az$3S*SU@c&M4O69fkj{fSPXPN zG^o<#2A3R63gGEDNVN`XO>u!*Q>>8I6nI`9dKwnEiiftQVB5n4kT389we55n7#*32 zaLH$Okn3=}q-W0&21hZBAf7ag z_vP*p21iX8?;wb04CBoK@l*xgsd86BR*5-eDS@R6n;I+wx#bN~ZSmOvkvn45t82I}8d;0vo`WZE%2Q;XzqVf!Xl|Lk?(} zp@qOYO(jN9Qz;3wl*gJe0YsTGg+M451x6v-P)%Y1S_KJd?||CPSptjXz}vSW zH0XjKIRz%}dPZ=zLgZ`~=q7H^N`WlI@l7la;1wt;AZJKGuf_qdS^>BFp-o#RM-h-b z{L&9_h=LCPhn(UI3R{jWfz65nJK16RdI0R-GQjq48({ml53v0^2H5_c$o7Lb$$^$j z>oPEamIb;&x}>lY3`8q1@(FSTPL2?|+7DygUy+iWXGjfKMq0b?G4$FnIYFs5ztnDgl-&FbaHB1lQ7_JJBI}KdQp= zAM8*jhb$%V&CsAWtO#fj0#vlIfL0*#D6lx{WPw%*GAOV(+GII`jOA1R#n6qCWLf=?_~7pcm3CCL`YiEQe*z6BQPJvK z#9O@vGDnIn(UBG4=ZLp@IjByiqOY$KZ*?@x9Izo)X*cZj!o3Y7!=2Ju$6;7(>WknR#}WEeCojX0+UG?N0lIvLz1 z0Zpi&pLmFLh5`5n6bA4SB+|09m16&MB1$t!>sXfu^$JJvvVw1CI$p-231*Fl1R0SjVU zK;Rg=QgbkXGf=)z$4p*KCotJ{7eb@{LC9K&e%z$#80{HGT z9t9TA7!U{eoF0L190EJpL8$|@<%vn)7C*NF3wSL6C^U*8Lr3sQItj?Y2V_nUbRZvS zNQ7Acl%_zVN#Kq0pcr8Wt=wk-4K_m#ITQd*$SGtATmemoFoRtUnyX~iU;-U{0lv!= zbY}oK{%at1LLxwc$#DbdhER3^$PJ;6N{-43jMCs}2AyOIia~IEQ|V^Va=7K-Jz$R8 zL6);XEN6672H6WbmIzdsfVb2NycPu|Ow=1m!BdGySCm2~^T5-;plKG+Wu>4?vB0;N zf@bAZ7`V|ry&GgNy*v%wMhY!%LAe(;;twhym_QQ;kkeGb`9xrvJnRr1@GL(lLt{I7 z3zA46laSymtU&X|kW+oYO)C`!ZW1k?LYBoEOrU$2Q7x{6WGP4*gN%MSvbck$+(CPL zFEc=yjE+W77L%hXl*R05=Ee)jy$Xy1Gc`dIqoD35OOYdoBjn5;Y0xQ=jz@Nac9IF4 z;{ok_5%>Zw;6V9Vff-i7!>k8w8s`C(t>CkK89;~QYA|tRfwMFyb%D-@XI5bGbgVB1 zXQkj*sDtt%gTOX1CD6Swpk3IY>0lm#b{Wtd3}lnK0wZ@7B!_|SLjY}4 zcTiwpaZq4%bjVghc0*xzylnN}7<5pl4Xa;XRcgS{} zuYeex7#b&h{rTQ3;n~VaJ zz*JCm2Obm~gf6_Gj^aX4a}Yjo$?O0+^i7}zdhH*BBbz&Dr3$D`2)WJ&{k(gZfk zn+DSIW_nqUtA1dDG&4bqk&r8^!4HlCS)hq&@TO-+5y%Chpz@ee0W@$Vk>&W~*g*z?R&G%Jz~Klwyuwig zTuU*y7lIm^V0)_|{SJt&AX~s!9&0c$WIM{_2|QK-w}K(ZtALh_fPDjM2|;RlP^JJk z2SNS-t-t~m;-Ezg9MGFfK^HR_y6rkoIXe}XR z#SFM90$NZAS_7rQ#3FE-2^7|hx(qCi%%D0M>H;Ou5)_d4SYX#?fi7tQwJ<^Vw}P*( z2dMy0Pl6g~UI2l~N3;$=OAwerldL?TW(TPM3R)bX09vajaD)xq z2xNxO)__**fs!E9P|)%N1;%V}aDd{AL4g^3fig&%2h zxg89O7X|@#P$Qg40hG!>jt3q6Nu|a=bTys;WXS`w<5`g9Y>>u3Xpn;m!~}%}XfHYF zzyhe12J z2xGF=DX}TAC@?xHbSSacDX}Q9DlmiC9CbBHj7|z|HA<|Y8XGjWz!tJrfn9;4PJvN@ zC1kCWLK|3DOHB=^UaoUusHp*677seI2A0vl?JNc*MmJst&~-#0VQ{$tI#1zB@}b1+$mXuV2;;Fhvbh(7{Nu>x#>)skc7p}P1g#8v!vN|gz5$)5Bd}J})se9n zbly7?Ker?D^}XQK1-46pNr2*IpP(oK6*`WvWuFTWhq=Pmdp3h|7$TR0E|GxUECuPw zI5uz)cNX+l@R`TZ1)2df!w$3$mPz<$nCi0 z*#QQ}W1tKvk>z-0@<9g2GtUn|E)xP}Q_wZ*pj!+;aSf{cKr^D?yVJpy4s4+jv_k-1 zXraL1_yKehxD=CvBZK3c-h(iAF@ZV+U~>f4NP?UK>g#|?bH^6OEXNO!b8ld}9q)7; zWDs~Q1zHjeI)Vzc>K)o?637zRAkD47@VR6kl1m^NrxSiIA7mjrs1gBSdtnRkA>x z4p6fk)Yb>rZ8D%CEGq^L1qOk;Afv&O(1G4sNFU1pa)1x0>H_sCK+|Y!;LRp13T&Xo zwXC3B8<5IMfyL1vONkwnCs;vjfpwao+Kdf!dLn3B0%*v<(I88aS%F;<6iM6)tf27) z@TFg%sSfZI0O;U-74Ru*;4{v!uY0(6Wg!}bXXnkPtc$=XwMe-QUFkQnh~@}8020a(7JihQg~+2 z*@57dfS|LWK+QveTdE)x;B6?-uw?x=;!2rG)06u;JUgZcsjtU%>3XCKU zZ2v!f05qM)AkZWX8OH|AuFg4gfWeUy)X&a>i)%1(fZF{SJvV;zxh;sy=0fT#JuBU}hc(DG3RZmPOt2P4_;0JqVp6&@U9JA;Mf%f@b}|!+Q+iW9}fEYGKppu z7rdZh7SIX5kdgy2j0P%gR2aBxA$6QUwjvW~@)$v1#Q-iyK~v}o zpy5O%@DL&cgBb(J297L89&k0Lz^Dmo@PVAbnWey_$-rn1RseF3BS#ik61-L%)YRdI z`rIK)2|UIF8bK6+j35dqFoTvJ@F+0D+ZxR9#n#M_#n#O5#n#M_#n#N=@f*$3P* zn3x$DLE8^B7#JL1ytvrR?#|2N$jHy_$m9q*ck{xvBMgqL0&6v;L4~Nk zTXjHu$EzS|(6yJKJGT+KZoq`4K?Z?U-oADOv>t4&rXz#9BV!5LT~v@RFM}f^sPPU8 zSx{{P>I@w?d>OKT3bdgLv`%2g5s&~h*NMQkU4fE5NcIC*IY^@z=#*vf)*?_d3DitA zV*+(r6qp1+8?L}hbjWtZ1-y>f0FhN-0_8u@loELB18B}h0yKLAx>^(25oM6cGRWKs zC?Fg+?mEEW$S!bSREZgM#5<@J2O7asVi0%>xmrlzm@G&Nw75)@nIQmFHVM2_1PwKU z${z&=flnITAO#9cjx1ITkfl=s$7Df!#ULe|0yB3BBO_=Ah9wKsumG6^E9D^P6|jJ& zQz54qKxXHl#}Dv;#9<{Ys3`)@1E7)(G?(Kj0NeEix^N!p00T!R&@=^XBN@c6pwgTL zbZ-)e5;N|3B5*zhsbX*hckNiftq0HwO3=1wP{SS6aRlWOh}ZbJ9sf)?2%jWc0vbd3$it_8qzSk!gGBG5J)a-0CZ zkJBJqiA{w;feqAYXBPMGHpB#JeJ7ESLoY0Hk2^;9(gg*REI6(&|^y7EJ13EZi0)8j_po0@8 z;&;M?KHBGqN%)Wr4o;Yg-w7Y+;Dl-TozT%w`{XzszY`YF z!3i_)J7EVMoG=r=6E4uf3A6A!;RPL>FdM%U8Ya*_InKfFgc)>j!d(1L*gyv-%){@5 z6F8gzJBka^y@w3lih#z5nFOAIFFXQWi^2rk>8Ozf8D(N{RLF9IP8dl*m-aI_iex#S zI1W0s0yL5f9)n^4oz?}K#Q>cc1{!PuZ4op8?YRI=p@H_MfG)uTk0yR#fGuwUU#s6bp1#7if$dycFvRd?^-KtK%D-3!pf%1U4eADEYtuTHAtt%Mqws&)}#6 zaw-XqP=PHu0%>%-gU<<@kemSS--9Prlo=cw;46;60r3O(Iv?x-@q^KkLtwY80)r!1 zt78w&r8OK`0xK|<8_~)cbMOVmDhy}PB0m1$T#3e!C9nfMK4{_soJ+qrvIKUby8spy z6W}Yqz$v1G)D+PHU-kvo>Np2qir9tZiV5IlU$h8_Gx$=&ZX_pwvj#0(um)dL>_vA0 zEGiJI62Vb%0{5Cx?3wcf11xibwL1R67Y=KXas^~nA}s>q48B}(06icYL3_Kvd*vZD z26$hA0)xPGIneP)9E!}2XCMW!5(8*}*8{W|8FZx=d~h2)_zkKc&drZ(7 zd&nFlNac=42N(p}M8T^UR2X2BeV|o{(0NWXCJ(SX9H*W=#Nencz#*^%yrP3cpiN7G z$?*h3mcRrMLm-m<6;_05lHF z2-VGRmjbO4B#zT46xP1^;w_;OJVB_p<4-2C*8h-cC;x%=WQUz z#(@?FK>`D@Ka>N!KU83)1ZX~v0YtDkp4fJf!BN!l!M1}80!u+2gk1c_An+G7E5wl{ z@C9_16?nlkR;$0!$!hShJJi>x+oC{=D#ReOUnu7?fVTcJb3kUdK~ssKb_ZxS3mjdL ziDLyO(DBHi^*@Z@nPt#{&7ipufw_o9eC3d+hVRV)Wq1WffktJ}VF2J$CUqHjKu0ft zHYq_5Qh?lj%b~#P$XEzDegU+hiN%qnBwLBWu^S?<9$|1aS730o$a1`~>{*PtyY0`s^*Tn^9#5CbUl zf>vj-fC7&RG?m5!y5|o($p+0tpd$!W7`RKp_qsZQ_a=ci4=aHW17ON_Wby?~0xB>$ zG7CKA0mUf;XwL{}^BOZKlFIyNvCSuub%0WmuM|Ib{g#OTOV=J)_4 z2yzIcBU_mxOcf({2_s8AXkHSuAq;%2HHQ+DH)v}MC@xtXIkJ>M;im+;3lby>Ucd+1 zHyffY0t#v-s=j)5Dx(9t1F39=H)1UlKw2%3rpU8dQw z05lm7+5jN{z7`l1$Qxr2|fyGe+w4+fV3!J<_XFV!__#ALPXzwF~IkN<4q90P#fY(P~WCyM1 z2K9FfAvQs3H&B@aUXB7@dImc5){n&jbo4T)^apLeRA6*u6zG)$m6G7?Sp?$}AVjLbhCiL0}~TTiY2Kz>Bg#CzJo10lt=di7YRJlp`Z(&xzxi znFkmgxdk9XOkknwAR#WO5TqIT5G2G76#`d*jxRt$98e)vM>eq54zF>b%W6S^G3-;gWmKQ=s%Hbmgs0Yx3 zjwS`21t$RR1S^7$hX4)GfTyMeW{HEw^f*9$Y!HJ-iP4d%Bnz@(4m5ac&By}TjmE&k z2s*zPJh{TnT}*WwcQArZT7y`*1#}=AXpm>A z6C6yC0TdR9N+w6fEYRQ>=rmzQ$fy`-KQClz33SCKH#cZ+4YL^&2RGtGU-cMw=Nr2=um;@A997S@nKvPaEN=%MSZlELkK<9=*Z}NgpT!98ip+mfk3e2WV3<@j) z(?k>?`@f*E3ZGK}&)k6~RG2{%Q{YMT568eWcc5erx*hEqc>NZ5ni)J!BHkl;F2mxki!*p7^wymc$`p1i3xHTIuq!WI?%E)@KwgQcU%G; zEI(b7f!pyrh%GDtVuLn&g6_5hT?xye%fJe9GUz5#$o-(8QB!aLf+o?x^BF9Kpxnf$ z!6f1Mx#DSS}A}|+JoFs$N=3_2pW>!qQMOw zsAhp|D1>SO&ufCWwJ9)iL-#Q{WGQi|Feq?*K?Jb*Wdxq#x`4CG)(n=A$JJ~Gf8tODqwR|N*ph1Dhs3<{i}!&5lGbG6v4 zU7$>RYjaV?;2EGZXQ1;rK=T}+ZJ5y63{WKtIva%pa=Hnmv;-}um;u^D_*@ZO8iGqg z(2NymfLj4Nc?OyshHf0Dl5Nk3vkf%i3(932imV`tL6Hqau_&^Gwn{QPD6lH9`|~m? zuquG>bWq}O49Ef{Y)3BeIiH~Q0$EC|khAZ&6*wFfiX5MUr{O?xtH7iHx`XpG7id>7 zC{cpB$63L1+mJDB&?W5-3Ji|WxdNiL!Gb0Z!L#nLM9ZkaAaF&9;4WC`^e1Hb4>;K^ z1sztx1D5WE0dQ{+>EM#Sv0H{A9BJfoebR!@%kxOI=T!Ahe;{i#7&RK9=v-<#p zqbRsC75D;D8Esez95v0~^2o%8UA0UT@$jz7Q*ZUqL%FJKn< zG*GDA8<@xoFauPA3xKb*HBmjw2(4u@$B!gFTeFPm12fm>Z>JD!1PDHW; zU-hEEr~oQIK&KwM@`6@7fsTv;mzbdApP4{in4_RedPTrzAUKL-DS}#|^;wFHkV6q! z9A%(e1X#dl*MZV23uyHZ=(fw2WuVOgpw$Z;S&nbk9b^D68iHQ_!d(gJl0vd2=#*MB zCLYi!grFmjq1`4>GUpMvE$he#I*J^0>=NXN5{1Ui@4?6oo2Ylx-h@}8NUmeuH;K%|W#-YKaqr?blSu=uK*3cU_p+~Sm+OUvy zAK-oflLE7VCTLw9k0K+8;!p%#-F;jcTzP`lmVrYMv^EUdB>}CQ1TU8Zt>l0l*8*yE zqTFl(U15jMP9ukrmXM0vC^r3d~uKELn~$3e4G{(~m$W z>4CZ>pj(1?KnL4_3NTPtM1k3nMPQL8=n`hAoP^`SgO?c`wZXT)I=%t1UmUs&S;?3R zDWqZ7$%0nCfpQkC5CpYJK;0qmDjiVUg8|F}ohG6II-nZ7$O4p`KrLL*FcRnnd+=gS zg)D(Pprwc40%Z*2N|J&oaF&M*8_CVJLohJMrbq35wwO3a1Tf8?;gh%m=MJV#xxhzcsVL>!V1GO={XrYAPTf0Z{z}y2uSw zUkN}@XwqbsP-1ba4+Y=k1lnE3DDYDeq<{z1&;S+3U1A_Ec)y(n6AO3|7iiTptOA2I z(9nE*7XVWsNKO304_2>t!IJLpmTyiEl@C{gE0#tG6lw1z?dcQ zKmv4@5M!3WKNSVg$Q$@XDA16az;U?9x8O)G5 z15iU5w8aP6GO!#qEt>$HpulDsSPq|MStJG{2X2pnr0`iqY9QX=#BCQ?4xeTD@MY+j6E;Do_CnjBjG#t5sG-6DK6R7D5p;y$H%^#pP_`6M0wr|NNC2qC0d@)KghxyV+DLpGHCXSQGnkObY+VIqW~j>0qP8bH!wM#0L?!=gu&aqc%YvK9nY34kd9{oyjce6`hr4@ z2{Z^qc)%ZRcn>t(ze}Cqa6fct1=4E)cQ3%B6KJE}piPP3K7l}%z$EDXV#H1l!rBO= z+ccR>o4TN*X%85(A^X)p!2wG)Nw}651@`Ucr*_#4_=BP0o~)mjmyUK zcx;r(f!GM$V+;-*q&>%ww2JFMPV8~If%aib-GXYd6v2WDx=;g>h(H<1aUy6sKnPSg zg8ICmtP6^4=xiv63z`jO2G53qs$XzJ6*|EKs(?=L5*z@>nqfB4K5((xyLEu2a4KooNHQ zkf#omfBzU9SK- zqnrskL2Go!W8K!s2r;TcJ+g~1xyXAZ3Pt{otI*A0-pn`v(^s4E3(JPJ(aS7HIx zU@V|<3D_YHkaHVci@>#)BclSdz-f7?YEWkobbvFXz(HlOJ_Ych4xl3)K*voWwI@K8 zAt*~T!S|*^_Sk~1BY>QH@QxL{j}~;M0kok6Y6Z^a28)7vPM{MCK-b8WWI;M}@Z%0Z zWeMb53m(XJUvL8#wEJHHRK9@wrr`53AT>8QYlAw$3<9yBk`y!%1DXf{HMs?#lRu!5 z1h9WWLye%uCwz$nxN!s;TL!PA!Ype+Q(fHokUkuSeQ`9hF9&=Cy9N^jivwud2fDTv zv=EO6w6qJf2_G~d4?3d&d|3{I5~HIS=*mb121hX~1_sc?rvf8rAPN+1u%UNwcMEo@ z1V{;3Eq6A=bCCWTbe`Xl&_;hyuz^k+fo$`CuBgZeISd}ULJ73(7F2eE1{I*4VQ@j7 zj%pXE+YVaHAqHMD2r>`3X$+b^0xgh2?kX;kgakP=h~j{c9)s)wPv$`@M~dxPN}N4) zD8mSh;A7Fj)g`D$4?6Y(G)V%QT44co=Q$XhI{)=uZ|LmbZx;kw5e6DB01eWB7SuXE z`Eh{3Q4*Y*9gl!!@*93aXYxUPCU7SRl*&0kwIp?*8SyYOYhD9o9d|&{v;>A$$w5Z|D5vsu_RTj zCpq~&-?re|zUQC*USJp)`!D})Ip6;H^uz(|F0_( zAAQ(3^W&re^8c}e>u*i`eXQxl0Oh`(DHjhf+;nI;b?RP{Gk?d z%`Y$hJ~^=J33WoBXb^qTZms=Ju{P=D80Qvvhfn5_1PQTXQHbC|- zyu5l<9{6zo(TN?@3I8HU zPZ}~L!Q=orfJ=i(0lXwY3ber45p=Suf&!z!YY`c_l;kW;Qmu<{M6l?Uixzv07hP@JO;_92)77@M)Uz!EQnWw@1i=e9V5JLqR}5&-4s_xxc!?V5Is;H)<1Nh% zS^)%_?`8y@zzSYbgFJAzQx3EgN0S+}tpK)ugNVexfqLE|!nSpEwQUPsZQDv$+qToy zwmo#UZ3kU#+e}y6cGA_hZPc@kP8(E4OMq7hfhXFS zL9_1ypoup4IlJIBN}!o~$b>m}K75)1bniHL;|L3Aj+;fFaT}u}V;1PpP|yh@py}tG zk_sT5;Asr_A^^zjKgeMQphM1CK@%DR6U7u*6j-epw=qJe^%OvDD4v`w?leZ$I?x&O zpv?q~P6C}E2~B2>8YRY7(7G#4W&tH;&~gTb8YLDdh0Yo!R?zY}1_dT3(M|={R&(fq zz|2m(oeC_iN=!9Mj0#Lnf}O4A%mSd9PA7#as1uvqk91A?+AaIFJcZ#v-=55J5-q?ma0`VZb8r2vi;jWC`q61FcsBm9(I02zu!bWRa08cPUz%-++&m znT3TBblw(&;{{lo-v-*|w*a;E6&OIbf_zj375!jlj{s=T1xkNFfx%G)sutD*0G&X= zt-t{48E~gEGS@RZfQ~8AXJk`iQDBi)1fAE%puhs!Bgm@2$jb;S>A(kufT9Mx{tC2r z3be}$6n4;IO7KPy$bLZuR`8BO@Wy>bCh!>-pnV7MgB?JN&;-7ygI3T%+PeY|K?{`> zAb|%8K^}osO5j=*Jhmh7Sr+6$&?+Uz*;7DUO#~LJf=&)(0-YAeq`@R1(4_)a4(iB2 zPj#TRjolbFA`U+SAI$E$|5@3ZUI%99f_%U0@Xxs8_@Uy436eDEmOw zt3dl?I^ZxtQ3~3Z%3#G{0A3gdUcCs;2*i|T?>NEf8djWr`3t(`heLsw;_R&$tb760 z5umN8prwQ0^>v_=`WTd$vK={mLHjrrm>fCLFNfmHQi7x#1;hn)99f{!60#vxfhkLg z!STtW!wi~`eh;Xgb9}StFoP}w_@KxnNF9OPh6645RAd0GX#?%O z0L}e?JMp0H5X|7Kg&1JsOrXjQA`ZGDicx_{;4Ck6K!iI6l8K--8T8ag&~7>nCQ$t( z0Xecm3ABd{v=|$7b_S?g1?5E;UjcSF3+O}?jx2$8Pzw~)RON1Cgb(XL_c}PTfN$CZ zZEXUDAyYl*fFy8}*pWej1vInB2%cFKxTB^7?yE3?3Ix!3KHz1^nqd3Em52rtXctNl zF9Wv%Gq)1>C|L%OLEuv$K*K~I#XwDF@Q4WXIyHFGf$S#%^&F4vgX|7rcG@?i`^TOo z-~VQtGlP>2s0d~jP+$gK5Cy7{Kn({bP{RQ-(xdH{dxRrCKe4lyX&!TH4w6<~y z+{$8^7M)+xLZm zI(FhtvMq3L-o7`j`P8qTW-D4-xdomv_aB(H=lGFD8{=qgWy^k8$o{|gW67z>?fW>W zV`V;UADu%MbZa+97W7hh4$u}7O=ba5J>f|71@Pb*Qw2uIt?Hm58qf)Wt9cceAji_C zfzGD@HOE0CL7@5#be1xxHemq`YHKhtWEW;b4%1-}xWo&R;DH>@4IV!LO(%c`JRBLb z3c*_fG?+lmLC7U#;BGPat}+JrzF`I>a3#n9I?V|*Bm!#6gU2qwMK-8u1R7m;6o4Fq zqQL|{0Ez*0t}&<@0G*8j9vt#^@ogl#ADB{QhlH|?+O+L8~Shv%tgrASURjc=%pFP|puE6X9r(1v-`td~6-~R9{4y&d=?5 zXVyUmM+L_lv!UxyK)Yig^)dKl3eb=ac!v<^UN?}VK?gT5a)Zvk5O^w~zyP}97gQsH zdxD^fg9%i_GeKCOZVG6m4Sb*r_{w6?;eVI;;I$L42jF zd>kLhFW_c3w51HblovGI1G$u!5tKv(W+O(E>15+Xy4yID?l$fapm#hjqq`rc)7{3E z2pd6#8RU{!(99sH@w$p1bmIW%cnnawhqgkQA-NmeVgs$90yR=Wjbec;fwTPJ4k2iE z4Rpddk0WCt_;?7|f-7)SH3iZRhGs(0NDOEw8PuP}HYb45oos-2CmBIq7|^u{O3WC& zBnmCL0PiQ!(2|x#7opP{G_>TyO9sD*ag%SUg!AK>b2c z4+-QeP~8i&3%Z>Y(S9^z0u5I4WC=V2(F~BGYH*Ktr!c6O3|ejlURK2n$}9|^&KIcj z1DdthVB!&2qA0LLQGrQd5eH~+7ThcV?JNXUx8U*Y6i7#pT2b`|YgAF$l9qSa(nB7& z@dOGE27ShBoak+gYmhqxcyh9ozzY;$V^=Jo$Oj#-1BrZa@9+sjPL^W_c!uQ(__!S` zEsZQlz(LC$$hntF%=(OMpk^6|5{qMfah4K;H6t6iZ2@XX2`o?n)#spA8EA}I;56v$ zYS7{DFmcEZV~{wr0t-YZxEGv`bglxpI}Yl;G73Co1}`-Qt<(jjaZqXmowNYn{tE6) zgN~$T;sGsr03~jLQ|hpBUr=`&I@-%@&IHOF;Gz_VJv-qi%!3Zt1`o|**aKe23YvP7 z$r4y6O28h}gA_nTHfX$Efzk2K)FTX_7NZjAP+(9Sn8A^=6f}#;!3$|5@_^6B&|ne( zohl4Ey9|7)FoOn@2&5q_ut*d%8qWe+qylb9)@OlQx(tw(uE1#~Zm>0w#wVK!g8~~k zmO%4>;M)rnSOxA#DX?iUaj-Zz-dTPLc1SrWTY{=WP|Fik_kmB2LfTCaN}5o4Ht?+( z+_CT)k3|JC;_Ao%y+vJtnWY|F46rINatlO(jyeWSNgh{*oI(tmvjOcqR$_K!a0it| zpaPgtfms?~q+57|Gz;%MyG*WyOb{Q=>3|%f zMx+nVbf6xyMuHEa7H;Sy$-)Djlv?usRDmRS#Zs3>*4%gdAZ79(5GR z0v{y?%0wVO?om%vb3qsSfR>ang9>!0xv-8_>kEU@E9bx34j<)B|UV& zS&G?lLKh_dNeZ1rc*O*nx#EC~1cRnHAG97|5Lhe;n#SY-ozw{$*#^zLII_93I0)PV zjfFB=G5CP`$DmU&pi`O*0-vQ77z9p(&X@q#M`YXZT2X-+bRagS4X;sc0G-hQS`z~) zni=?*85o(sr~Y$*Pu&Nfdk<>LgW`utfe|!Q1sVteEsTJlI0~w3L3IZMXq^VAw&Q`E z%MU5VL8pu`a#LUr{7_CB+XFw;lo)%U!yoW`$OLXZg355vNRSHjfR5k?tt`FQC~F)Wm>~lz=KN&~TL_ zOBrNK0E0B7vSb3C)h7ZPe*w+zfbt2rjuybS1)v177y%Tir{;ohfLS67T6q9D-1sU; z2z`&9ZryI?!X&!7`YQbvpC@O zSfKO=%KD(;F+LUsMkZ!fNYa6<$z{m`&*6ZEgus)*0?Ii2(dU3H03F@Jpv&OG$HK_O!~j~@>*$az&?BJ00J_)WBj^}n1E_hhTP$GH{jkYo z1}g?v&`My)vS08$c;I3V!Urz{=H|{}P+$-^rUqJc>;dV3F*u%KfSP;*#(2VzB>=fY z;{%wbz~BfvSh+)8fdSMChAc}49jpw#{R4EcGFS?9P%_x-dl*3`Qj(eAXA%>W$Uy@O zpvWPkZ~zq_JdEIr3YiF%4S5Wp@laR_01Y6*1~A!_7#+EMc^P4&k1OUtM;{$u%s$BA zXy7;lCID*OfjWMSpw>KS(Fkq3M;Amns7(25CAgOU*x9-xEO zSQMDDl|X0Tfie*2oP6dofh{tiGfa811iHmwOC~@w*r0F*ooK}hvIKIX6&qwknnQuj zk+BfArj$kCJp4Q>R&LN`WD1D$tXLhHOR|+19BZJ9?id^^AjeO^8uqZ|Nucr+sd*y- zT8Rg5Z-6%Mfx9Wt_6BTxivx6=mg9=f!=SD=OP1pf2#X`j@j}~S27%pdpo53Oi$CB6 z>Vu}k;LCs@DFi(50QNN0WKf3>GI$KSNCVuI2g`7P*8e!30GSUup%}*E$Z|Z>jKiiY zJrvk9qvtTF3(1n@2xW0(IqvAiVbhaUWZDF(209kQY=W{lvK*hRhS~(3d4qPynLsIl z0d&qYxc35X%7B)ZFgP-0fht8t$KHiU7#x)yAIv(!;0U^l78ECQk1#mynRkT2krNz+ zjypgCCqM#R3gETF8x|g65a6#-9jG6E87wN{ID0rpC#b?EF3Q^zXBSSaAk1--(kT39U1^N zB0*gmM@DzhG?^w7XrnZP1``Kpgjxf9!IC2bw<3e%o#j`+_vVr5cII;*_RaasHoi7Gzhs!8{7cqmDeL#ElEvrG7FG+yvCU64{To!}+?T#E-W=tZE z2UcBSP-Fm8pd;w&6&P3rc5{MO&i~}%=LTD_P!qEx`*8v^HUQ3vpdudHR)m+COt|_| z;F9dXvCGi%1rZ~vWCnW0OX!G4WP6EvIEKjW%=jWeM5mY zd*;BbfwDNV9QU+?#s}CKxC^0eP)I8ZlDHW7co~^MfSHArjfn}oa0$6_`$!Gc+JuNe zwxF?O33STA1Q9H7lTaW_paU+~A;*orIRrEv1YX@M1KM2%UKa$K4gk%?LY7H^mjr?0 z2i)mk5K(|F@)a~^0Odo___m`2^sXS-<`7U$g2WPJm=wI4o>Aa~I%pZHh$16&Mt~Pw zSAtp~pyE#g(tZIILZGg)zzQ+YZV-?T@cD^60_`%O&LU*iL4lDw3^MuvZPb9$k^+Ok zJ9SWF5j56zOjd~ryn%qliUD%oKImX*h!EKPSL)zOTi}>1=tywTh=K}(0u#6tpxEu} z3AjBQt;J9yxh{L140q zE(5q|Wds$xpeqqYvcS_I+)NG%te}%}K?OQwX7UO`g95VxlW!3yHWgR|t_g8-Qz87; zgRY8YQeY5ROd$M1;Bf^y!Wq2wP=g6n1xP6{f?Nt-*#|lU6V$JOjd4Nw;2n^lH87y$ zDR4y=)My3|@#iAtd{D1Y1$kLIfvu?E0T}RBR8T({)*l65w}`R7eLWU;=en5 z@Qfcg&A}SOpbDB7G^PVu!3M4%D4Oh}QW~5y?-H$IbH`Flqr<`B0xDW@F8vdD$_g&d zLG617PzZ{ECN~LmFF+>^z{`11+0Nkj;^alpZZQqe)Fh~3gg9;+JdF%$>Vev~pxTSU zT@iXmCTLa?xT8XgO#k8trqLM;kWE;ODh!Ti zmR$kut^rSk$Uukr89_THK$kx)xB}`Eff}RWnOX1vn~nmb0_gH6(DlS17UZT~P`> z;tHrYBF6w~G=SHLP$_tBJjUV&(4q}cqd<`v(iwp@3BVfzKv!acs!>MAdLLepD;dGv zS65yp&=eKu%=mShil9ktMo?oOnp_wZKz&($Zh>78FE9##dZbkH!-=*l7}*uHC==>< z(5L}uT`U7169Xd?C;(Zq1Wu`g{h-Uh;>ZjdH~1JsuWtzQN6LH$?I z`4iw~A-Jms-ctg}dvI0YUI6%F5l|D0N#LL&+U|EI(6(q{kRQQr0X5*5bQwUG8-iwV zKn=M20!oaa+sa^bDa=+3jG*}u&{Y?p-V+08xB=8}gRbudt+4`+pn+QM$_$S1%ho|f zLJl~~JAOWOh`~`8wB-(D3s_9xpQ^wTRgfb%1lqI|m>fa3i%)=d0q&){f_860D4-0mCKm|EccM&w&0UE|Z9qj-G z0yslKM>`-bX;8laJTTlb;ULHZDCHF>oIr&>_N6iku*K=%DOUwh7X+M$(bt9x99IWz z=>$!fK&xN$72&R+iU@qwdOc(>kpiOviyJSalmcj_9BA%Afk~hlR1+D1)@6eBfhsbA z_6&iRm~$&I`m-vqaC0X@TFKD9IH&{!6$g-GTIv;;9L3yN9AL+^Yys~(1!X?)JQ;Mw zHKPJJM=&ZdfcFnGDliJHkaq-^ec<#-jc~@+gr$bL*xIkuFc(`3lN#n?YhF^rTx@Mi zYM6_yVMz^hv95TS<4u{Fx5VJ^026E)1m z)(j|OWU6y&XxP(r@{+J36R5Z0cz~f0R9AvdSakxmbL|V)DlxUe6oFPoWINgyuI*@1 zWQGYUFtsT%@i213`HUbHZHmlJ44~mc1_jVfT%bj&pi`>C7#Zup$5BBoVul>$%Amju zHn$CQ`XWfX5=%!5s2Q%n(g8Lcw96GF-l50{GnNrl^@C04;6{WHc;pE*PQ(DY^#wG* z1}QzkEeg=8R&Xl<)V2gK-j~R7{Lp-WLExDpsLjJ5uumLPmV!nfxZ@xzlc4jPi~%h5 zpeu-(KurVi5^!^7(3}{!%_5NHc;)Z`2FC*+!@hxUr3Fp4fY!QlgDVH{?epMERY6r4 z*!T?CGFiw%J11t)7A*zFy-xpOfT4N63j-K@s84381I=<+G7C5{f$l+u)QSvN44^xs z!EOK(5?KQ4L31mhnHvRAEu_N0-2%Fg+R*@ftcen%BRgpA45K6HJPXi@8AeA=(E3M4 z@TnJ|<&KPwTxLu%3XG1RlQF>UZIBAk4bY&|GeFflSOvJHej2igA3RJ68Xg0k!U38w zVQ^||XlQuA0A95YY9ldlCqTwmAf5$z1vIS*o+<`iB&q`K1TcX*0ic;h*jgVZM;4HK zK_lOgwLTygXmUpb(!yE=e^-qHiD z=ms?iLG#_<=`Ha3T#hV(7vcgtL5rlp*@Xt?zofDGuV`%kYZ{yXmd574qp|rPXl(vR z8k_%##^!&evH9PS&5r>e-3A^$0QJE*l$ag={r~@;-5WGt<;al*I=c+C+!nkb1XOW@ zHo}4y`YJFwI%I>^eu3HCjq5@_^~xi@Nzwn4d4nBGF}Op4r0XL zT$%C@)Di+M+j+~0x4rUK47oW$f(_#hw)v?Tx?TLDdKK=#{nWC`5iAuv=A+RF;M$`Lfo2s>@k5nL324l)1_o`O4! zpppeT0}CE61eFV*jt6KCj}bJr$OKyK1m2Zk!?JBs9F30ws&0|o76Py%nR;}AH+1ZvN* zfW}S1(;A?nN`-+t3LJ(Cknvg25uA+t+{_N(kOWPZfDXt3$FVzTkP|dY3o=uISzxUu zFKA&RXk9V5U!(}?=7DyG@iK6Oj~rqE$0h32h=2m9Ge(U$5l}ioGh2~bX2(IQ0D){J z*fujz$brx3Vi1_XsK}(ig5(9zwlYv(7gWqMxLYwm=W`f9``5p3bw)@JOl{7+5*%NV*>RXLF?}vuS`0?Ag};*AU5P~b_NAT z8&I1K+(Ls6apE(Y3ADJGNr90}qfy6YA+D|u$8y92KfavYXLrN z0@Un89@T{H0s<)l_oG-qeKtf#859zrjxsZN-7mPK%&5R3FhLY__z!5|A=rPQ_U$oQ z&>=LCZh`_ccQSIv1JsXkgzhH257P=-p?v)2GHFJEa3Ak zV1Wc$69<}QQDO!k*8}nhs{*qlb4iv0s{#v{W^`mO0bLgZGJyp&Q^*9GX95i~adRUd zAp&mK3p5BrCO^Q7Ok}bIE~|n%mY`F49Phk2z~Ct4c;xK?27##>;5m2DaJ~kUh`@hY zP+)2`I9p=L=Dm#DT^Xz#EQ1DHOCLn3)-J zGZ6ZYV3b3`6&M^1pa+4&b_7d6b{d0@%?2&gfNVELgJu!Ig9Uj$_y&{52gb#>qqAVEVvpz`pNpb}^~IY*YjOi@sWpAj^I z3_8<@S(kxFfkEJx2y9RhHi!&$G_1tYWngd=0&S;;&Q&rx{+V=y!4WbI>DVy&2!lW) zWR*T>4hu9Z`T`^m8iL`;a(puhEDv8l21+st435h-wRSP*D1mbD&d+y0R^}A1b(+Oq z=cLfF+>x=wvFFqYhAe$X1_g#JM~J)vBa#ZH62}8KPB4H*jg%Nc)AEiSWeN;#(%=iU z;NvSy5Fda%4ccD`I?@I-@4W|fmJeuFjU&tP$nr}_t_Po)4D!GNkP_(5$~6!ra1WrY zoW)_qn+=y393cluIeyuI)ruP+C7=~xJXwx+AWGm?fMyEdzJMhe7En6jPy*eP1736s zttvq0U$U%qY6Mj{b)ZR6Mn`3D(6Uki&@Mml0Yv=Vj_rHl=NF~ID@4#@0nm`ytepoy zha24&g>HmGsSrWyuRs+dXhRf(;{lLT7SQN4h|dTaorWp_6*i!03-InJP&7llz@h>g zs$&3cLl?L&3f`&(E*QWS7`V;_aY0sqhD4b`8*QYZs=#C4P+3sD1t}L47-4%Mpa~V^ zhmD|JI#M7DKrIAtJ&Uja#06OZk^-II^<17%jh+Z9^ z3}ku(yp|4h3IllHm<4p80)hpR1RpDbbiBk-RfG!e2zb#69uNgrhwzo3pw$7Oq5!le zl&M~UNnoBFczvw`cv&X$P#t)yDrB4vS~jFWPT>I6ya&!6VsI3I9;N{r_+@mw021Pb z3V~PRI^G2d!Bl~d7jS$F5)y=}0-eGEGVLEokVjyNtTZ=j(F_VA5~6pPI-%&LB=Ky~ zAY?jpBMnmGc`@?<=r$vwT7&|}c?l&RObb4MEZ`s;YVeF@-JxlH~2m%PuKvp`!r;B`U@tf0kT26>R)sHJBKr;k624?g4bZD>J0A z2EGg%bPPYEKtCV&YGBa$Qm&v0E@sfFO-$hCo+AtNwrkMFd5}g>`V~APcyNjL+YKq+9R@RHbkdX~A+bGA&6#)Gk1}4@e54 z79P?q_yCFnCL)9AFBx(031k5akrq7RC*23%Ko$rPVF9S0b&QOn|J&IEpgNeig7Y&O z1?Qbh2N)cgiSPj^qkYmK6hw&K@}P1JypDtiTrPl)QxVvz0xB6mO@E#&fp3bSCMgSO z3ys+0BCG&v#HQ+%+$ii9ZSyH%8WKjScwnY?nUUd{CXdxG5I2t%| z2Poqrvhc^lVH6@JTWTSpr@1phY{N>mV5w7$BWZP+t?gh6FT}>yVAL5zq)~ z_YzxtpJOFdHbKJ}(sBoTOaT<00$b!k+ao|DETCl~j;vM;kb9Xxof6QMw4gyO$hun4 z5F)6F=7=l)P|cReqKetxpiPsYAwE!}4RrpH66lgtP$wO9-XaV1&Rc;upg{=%(1DqZ zjs>ubxj^fPLB0ZQ+5??g911x(1C$6rgTVqyjG(R2jL?02jv}Bj5s(Oj29p42!3?N# z=2-6r8a4-y|0*#$)`RX=RbYgkiUd*wUh@K02@V&~C0qV1pfeA_hBGNJ`hpy*z~siu z2tG^^zR2M^HRPDs)QWe0w4$BwH<7#s~8Tdo~p5a^R;;Esn4RzVAY&?Q#j zmHwcR04=X)QeZY`7GMV12TH8q93`-e4OF>sKn_>}^<6=O9s=)FU3o#r0YYXxKzBvD z!`6($Vh%L=2)g4DTpdl*5|}LpUgrgF8w*T@^1(;I@ni{12lGKjD=|2#fCg3>5aT9D zCWBhcpk1#ZH!%qGgBH_(*W^L>NP|vp01Y#NvH}CzVj5=fQQHiTkWM=2JR=p*8Y8B9 zM;7R=6ISr))gTV2+;FVU;$vcB1dpy)W`XurD>6H>fwzHxPW1zg4LY)d##$IaW5eL8 z5ZsXf7bT!5D1i4&K(1y`0u8u=qMk#EH5)XrknJdvr^E)jU7iJWpq{`rMaV`~@Ldm( zu^$d4@X7bg-~nGyWzGz`-W{|+3uF}|Xgi9)Tsc_dACWD=cdCJkJOyy05Imp*au+1E zg63Dip>|9b+(%~+c&7+vpsjLbgbhe4FmeY$iYsW+0VfXzfnyw?c;EpYLJnHj1{!Gu z@1q1KUXTl+4FzVdd6_`OYolGL2 z!@fWp6+l%g(p>SEZ^TXG!rRoKS`t((DL|&92^fFnJ5k1iCR;H|B7rREpgyQm4B7n! z-u4EnmBBKg)gRz6?h=8`27<~Z@C+_&mnXCs0u?@>Bm!x6FoOFSERdECs7(wh@*s-~ zAXlb>m+ylv+WDvoUx5KFhQO!TLd}Kt_#GharRA!Q{}~IF7-45ogJ;`8lL6pX4ycC& zYVz=830#u{^;TfF@PN$?g(Nx1UVl*I60|mf3EDOVpB2pHr~q#IfNC!u(9y4ub{lIM zs58Qo<@jRBK?Z>iA<%jb=)@8;H!-FPz)j^qn92e(^#>MHu@=RfDbLba&0R|)bJx(w z+;!A27kt4KYRg52+!n@Ecnbr%j|Wz)fp*LP0TnDtOrV3%!Q~gILj)=*!EM4CbLIwc zXTq_8G0Snq#X}4NixnZchRG4EQ%ZpmbaMieBcynPPDMFnDS=nVfX1OX6d0XA>zKgZ zZv{rjIe!i@2pm!ZHG3UFt5!r<92~d&ImF;-uE6MMk>z;e?;!@q9e)ooKnrexR**Bn zJ!UM6JwWRxz(<`!b1`VyK4?OL1#}+20BCUq_)s{|;jW-XAK+tNB@`IIO+k@{$f84qRclVsTmlz!X+`fdx-O$nv5}n}DLC~fO=;Sc?(0}l>0jR+% zu!akC!42&AInY2M_`n}f#|1n<2r9loJt8KSdd51?A|eJwHgMS}a9kd8Cl`+rcn=8Z zPBO+UNY4c6PA>433E;jE=*BEI@V0nZLl064!sc2HvXxj>7!+7R%|a%yqXZd1T#hWT zn7|ET1y%)CQ02lbpuh?;1JrK;opU14E(;bASf#GOAh1qDfz=T_Faw>$C1mhT+y-|* z4PH)`!MAW5+zB;!D_I8L#%*vH)Zk5I8GHw~!QD`U=aFUbUEBuuKnKGH6XSxHBEg0CE^;en5fA@ds!XCTPVTsPhkMd3WqOz~IOUTCWFM zPzzckufXIu1tiEMaGnS3O3>ks44_#e`07DMuzx@sNVriAj)NR$9*3L7%*#*Njut4PM(pxn6i zNXA_!$+!UMIV-vh9H5g`K%-9Jt0q~LSU^XuFe|Y5vp9hBBO~Y}Gtg8qga_KG4jMCs zuC@pDP(f!XfajnEEXaLZ1dIePP6Yv^1t!M};G=f~;7bgs zw7LN5MwCfhMB&H;z2Ft(Ah6@HP2)m}snwu+zZ5_vS|ohN6#t>FP3UkqC* z&tS#`%G;m`5zyu%$iOye>KZiR0J4lDOW-hQ$q`4Ez;<=e@HMzV#x!{&%}icTGm}@* z%;eQnGMSolwQE2}6oS(QHBIdU?ckxhsmDPLHe^#BvcLznKnr$It-}afpu=3Rz#?#% zM~T6)q2UOF8%wfx&XXebe*OYsL=w-DWKMZ3Ilf{WLpWy z@gG1dPPswFH272`kkD_C5bEWwjh7FAt`h){20Jo4vVaDI9lJq-pzSAEZgPdr?7&Jg zB4!d57#$CQiZAH=qz8COn7}6JG$N!hg9b+f6Qq13&eRV`vz|Xd{^Q6J*a|hafeBRp zP|eugD8@p=0N#IK0L|JlJK8HSgJ$lYae@L7+*tq-EJ`c_6T}o*K@BtomTX9;fl+}a z%aK8WRT>#~(h8af~1fGgOdZN(%Yv4n}7{SGZ0+S?ZW_KfKEGvZ0-dwTT)<_1|?T$YVty^%t3uz&{9rN3kTE{ zLf$M3TKonsvp~B6!HZAf&W09KSkEZr6JNOF^L*X2B4`)27!y9iGGtT0nk7&=>F*k(h3Zq`=~*S?;Syx zg6$VqU~oLakOi_2+0;`YQzfz>rb4%&W0(q>8z9Nlqaahk7g&SW^b6b(1^WWkt)MYE zkf}4|@VGS+*4svEDhljmgJgHe3O&aM6AmyqiVOTv0rkM44Le;1@HxoRbXZVxV;n zj2cWlpezQixqU!eT0t2cwC-4e*%wqmfzF}>U!lRMzzkj*yT9IxmysJ%qAD;698?0O zH&FW%UQ#oIdz;0KjP;HhkYNNyM;^#o)S%6lpi}x79R(rBF@UyYf)>j%ItrLEfzF}^ zZQBI7lF^YDR7pU#c7iHwunHDX-FOysBqM_YgHvlmL&F8+v#2950vfgD4O%S?ntTP# zcY`u4Xn`&$790h#99JAVz~HFoc;nCk27$GTpi)9$hbk{+Mc}16pq1p{Fq42S>Oq_b4O!F!9|VG^ z=XOI&f)ZKaZNi{|A!bNY1NT{Bd}yx-v}2tkOJJiS`1T(a25>2%%-{%Fzz-_VL5To# zEi5zW7;*5zW{xb!JADVill!2?i$s>dZgqj%^5Cv9q>Xf57POTZ)I?wcH!8_9bq^s^ zq0NK~jM+-yRaT(PAh4GaG?b~p46WJ0Ck`?@vJ^R<0JpkeOD36h8NefyuyxZHz-Q1R zs$3?>zH$vF9#Az29#;YT4IGHjkt;;k5_Es*1u;-R9Mo$D7ZEB93XI&Y;J!FyQ-%`w z4r&f1#%vY`aPR#MJERZ>(+Z%@IFmc52M;RVz$a3|7UhG-UO=fF)TsyEM+;gY4_Z?O z8GvBOR$%gEaR9ADR$zh;KrnEF8gZZ_4#2?zYI1{WGthO{42}%oYfBZt&3Djp5zsgi zsIUR8!w2olWOn3$+zkx6s{nK;2)HT%tpWrk%o&Rzmv)1zNCwcQ4`Ah>dzFGAsSq-p z2|d0*i9wT@Apm5w7#vvy-l>AhJkY5Lpp)joMmrO)G(*d++j9jN~ zSaAe=XF3+A2BGw1VEuPTo-9WOfoYnc)*y(@2x2pXTLnrikTv`)pf&v9rWGha!K+N5 z%>znYdgeY(mr`QvjN>P81pp<+u32yqm$AO!G!IIuSjV40R}Epkml{&CLdT#$%`;F| z;toRHZU8ct1=QkWP-1mt%u-?l6*6oJte)Uw@0me|R)e-1Gl9}8c=ItRy|QE}Fbn+S zfNdzCnvwtEMuJKrP_|_N6&3=!xxrf=a30GmkR`AVbd?bcD9?lPAhfl{0J_^7dO}BNRFt!T2nHoqaC*(=;l@xUxTjMuxLe>ZqbRtW;l@Bc2wNo#>VD(h`~Xf*9pKg|WP<`IJOIitK5U~7WY+{}gDbeO)nEeMrUlwC3z}nen$=`A5<0aD<$VOn zvBKnDgLrH(-W?E+AI7@^;&BLUljjD{MT7cSN>u7#5%$8A7l%R1YTkhw1dNW;{vT#= z)&ApM{XEzE=VQ2z&lm$Ak@JT&`dq32PvS$BESP0!vSqs zR$vsEq7LfYXfW|8F+=(@%#i*J3uGjOaV=`18q8?;N ze1doZp3Y!UB+%mq^^4&5k${^pi~?=SkQ4V57#&qWos@Tskai85JGd?524OfM}($N6j6a~pV@CgeJ$T%1L_P#TCZomVboB_JK8hpbYxP=VfngeMzbNfKL zCa|VIWVYss7dQ64r<2wL)C20Akpd<8w!Fi-*q-BOKw9TsSKbOPuutfLI@%di+Aw^DO}FT(9&I0U5`Zcj*j7@$mY>;l*E;7#g`jvAnym5}=qL1WIK4evbW%nIP{jldQz z&;$p#@PZAOpr@59c+v_>3F!J+(2?1o`U%{_2enN=sgjw2+Z(zn4>Udm-UJGnd4dGg9NT9LmF|Q5&j3$4=^|~fG!kgaBN`&%|$3MIQD?lqJnwhxchv>k(f@UPBUjnWNpc5WS;Pdf8l?>=|Mg=C&N^us*L>m+Mu5Qrj zQlKW*nd7jbc2ENhJkShM2bp05tttT3bKsFw2BOV;g3nCY84aKv%%CB5NH+vhqkwKr z09^(kEfAx?3YzXduB^Zc8ZrQFb!XLJ;&6m5y#XJz58B!cK4BJYCj5X6(DHv!LmfOT z!=u3L$OgJogBh}mh1n5wQ~1>b3<6&TL8}EpwL0h=Mn`a)of&dM1*p{k8SnU+n(6a)?D zbAV4E1g#kdtseo2FbK@%RRE7lK&B}`Gb7MtfeZql6hTs82^KI1vda&8Dg$)yAV@QK z?Ima{2W0y?cxw}PMAfE8-NFMz-!be^MIG_ zg9k4i&rCZA8fIQ_>LBzsP|!V*ps5Sc_!vhP*g(icA!1!Gc*F_nLdZt5DNrLp7can# z+(5LEpf#2X;6Xd2OD#cbRzUkwz>8NDVAoncVL-aq60C&T@dfL7N) zNAE!6|FE5L;F(SM91V2l5j>L#zJLIybio2>mk4O}E3?2_CD5vW5F4}u z!0`%bJBhO6optc-B%oLaFUDk00_{sSut+VX#|*K zSD-yQ9H8M!kc&Zcn2sN|fzAvT_z&8{3tmkMAE^UR!74BdJZ1(>U4h51Jh7|`S_Ymo z#Ii1^hY37u1-cbVA}34Wpd#{`ASciTqo6fP@C#}cL9<>wIf{(Tpga1&#~OgrBq+R2 zGl9-u;K>3jDaitz1JBLP4ZSG=tP(uk4B0@z4BbEh4i5MR3TE&kZU)f74WOWdY@lFL z0Pm`D1kE^tQ=3Az5`zjTNxoTf1w7=&;P?T|0!=3}I7(!J_RoOiA@ec}pz}3A8ImJQ z;0$ODIC$->1AN92VwOx6DAYl^{>%q0j+RhhaAJg<{4!$!NC0AjW5dEr3lBbbaH<-XbzPb>D(4@mc}(c3rg*X@!qq%-~mVQI4^jU2Iw|XaG-$p)PV{s z(0)avJ%9`tI|@OEP=WUT9hbzj_YYKj!Av_WufXW|f-y_r9Qb5=v~7=|gY`hh;oVAz zY+O5N^AuVIs9`Y;bWR~b(~uo^MHzBTEof6F zX3&8SxC0r7cZ(;oarpfTI=~EM+)U7Dv_m#%wF84A`i@cJjRTzl3Nr2?z741#`m>} zDhl69fl6-By7+m@jy72eOafa99Ys9nY~MiyPg6J?F@C z;8_$0LKo?NfG!6DwX*On00$R70_!wE*AtsDy{0lW|hZBZJe$^h+_ zd%%zdn(1P6{Br#egCm>cFAxQt(cW|85QF1?kN_w;c(NSN+&F~1Y63cu1mB`8k_DMu z1D!U_#G=6H*fA3lij0oZ;61@0Yb8J}Lue(&D6mKcJlUke09%?xiD9S3VTOSUKV{f1 zAJG1M$NvnVJgctEpd;Hh)0mujz za7!B8&;idEg8~fHa0g{cMo0r+3ADZqv^-mbi9-rhLV?c;0Oc(X@b)|CN;kOg89)Ys zjy^&xwAtAPUJr5vMDc+q6&D61<#M?fKB9CAPw=(;KJdMRR- z+5A9T5<{_pC(sOpRs#@!gVycnGvaWZBWOo0s5n4gvU3B?I4tqY0Erx8d^-c*q9RB{ zfM%2ttF;9IUe^d(Aj0hl-bM@A6bsJ6plTg_+8n5>2U;Y7wAmY9Uj@7} z7n0lHLjnw-6@K6Y!NC5I;;v*$AXG0 z76oR3wVJN13QXMGe(=@@xRs#61UkM0>;VP^W>*#m$2}`9F*wSA7gU0pTA&mH+C}dO zs)6@`mfG@U37mqLqGTHfs<$wW0}TQ|VgYvj4#*7xD&(AKgJu@UAW%!sk{q)@i5B86 zP?HkA_D8@|kr6z`B5+(8bdUh#s2$MBvPvxQ^**3=D=grnb|Aw&;Ijv@8RkVz!y>6^ zSTr>aDjp>#Xyq8_C>PM#E)3@2EBe4I+y$}(u7U=?zynqw1&}pmq?>X^2-Nn3 zb}*nP*7}2nYA!H<2d@|$@4y%@V2m#eS)f%|44`Xa1VCpkIi7&6&%VM4krJ2AgL-6*IRqX6n!uaibK44N}hYZPJ)TZ`Q=FG%+b zwz(SC#Rn~OoS+5jRZyZ?yO`yFnkWJM%@;ap72g(-U z?fIZF1z3r(0lZBIHLsIy$`#O|Y-r_<1H7%mr~*1M5wi772{isH1#M6%FbOOd0i7EL znHd1Jb{M2VTWG+M?*|`OM?^lXe<$!$3LO8S^A|u29wqQ%Q%2B@uAti|!94H*HlRQv zY}_yE8uy2~#{DMQI9t$60{W~DQweAgjmZ&2!{&6DN(5GGN`a#fEDmm%lb!%>fo`ow zO91YWbPe0=1sa|N*I}Rzwm?58IJQA?2RW8bV5d6hz-B83Q0f%O5;z9BR2#g*%MCdp zLHAv+#F$@k1nsl~oxB68eZZHO2^)HUuUCC0gfvk_>t2DH73fx#SHGjoDA!*OJ3 zg7~0{8B|k44~GMd+k%8xvcMZGL5HPTF)(mDFhI&+Xg3X99D({?99aT?!6&A0pj;yj zYVJ6)6bYOLofZJe#o*Cg$3M%jfRYiY%hRyp3WEXzXbf7Di2*eI2pPm>a#HA64!U>( zG{h^-s=x@^-3ZnP9u(wu1nJ{O%+Vss7{?tuE`g3!Kdb~9>e&zCg1WRvc3ff*xX$Ky z1th=@o^p1CiU~9dL&soY1BU|HN^GD5(m*8^=rjQq5Q7!ehY3<(0~O}Sl@-`vTMXDR zwivKMrldhbn$W%{n1UUn1R6sG-AE2H2;ABdfy}0W6rpb~p1|nHA^_T6462zy3h-@O zh8YH;L2A(rGk}^!jKg3XpmFVcJ^|bJ?1Y@dK{XzOqZs%g9Z;D88ZUr0c^N^&-VC74 zk&FWK5gk=@~Rep#dIRXD$Jq;9mjiErA9vm~|OgK*#OYfI{4n!MzwfeBlTQTgada zXvh&dw8fwc+TH99YUG0&{NTxJ(9i|w21fz#ZL6?h85_{Kp)3l_{wxll_L(;?sLjWs zz>GK%)RDOav=f$}8?>iKV2LIJX#SQ-V6i5oZw7Whbm{_IX43edG>L^xzqBfvb`rFM|>#PnN)CRfu^k z4vwd19|9fM3fdzJ5(5=P-~*e%XJ4u?aHE^ENe;=JO9*o|fXtDG3=M(e4P1Uf<}bk| zEAEtnexxDDeANA$JJ1G$p+{~Z)s2^gK`E4h#li8$v5N@*C_ttvK)wdINO?dB2-F3J zb|x?lx(qkyJ;)$YsD}s{WC>~zfhw{3EG1^pL9F1Tycj?SKZ28}zMC|wBLlY*6L_o# zR2(oWfY_k$h26XgsvG9XK!>+*M(MbX-6U1x8R?0BNJ#PYH0DuEKz|u>!tGNrMU0MFbt6 z>)5gnx_A(j9>HhgfR~(bC@?s!`EYIX>Jw}4Re~x|Xrjc{{y{hL%Wj-TKG{9_!Q3BD z&Q~KDi8ew9s=~qdf`fM8f%?^;6OgCicID6B=f7S*+kN;ZxSl7$nNRlObmokyTlRij z(y&3BL}y;X?aV*(o_^i_egD+4B0^9gQeHhj4?;oOq>-AhR|^9b%3T6k;k?uD=aZe5FPCNYU~3vPGL**dM``LXMF zQ%LnX?%-@af1>5`QKz5C6~RsAv~ z8hHh`k#nbfpLyWVqH88dMiQ0NaeI90$*VJW{_Q!x1Ub%$F|!4?neE$dY+3i}R?A0H zBj^imuRplGe8Y@OUneOed7YRD+Jd|E*neQ!p5sRrZHyz)$d>&$3y=Tzek?gPxqTl8 zl99v&<`vw5x#nEYvK{~Setbx3U>?C8nCJFQTsi;F>Wk4x&Lk!eKWd$>{;^t zZ#I&V#Q6LRZlAwzKXK#N`+NJokm~a#xPAWae&_F3H=bV2MRF!FK7WGS=R0=XSbYD~ zo#uQbBZ=|(72GA<(KEjfoxZej#s=g}NsKd>;1116dlyVQy>0$a5hQ04Wh8E&|2uzq z*1_)kce6+|atfXd^nCg8uHU_{N|B7T26Z=?6c|C>O(q2vU(m%b3M}BxBzQSLxO)li zEI>P;pvinDa0e9DFN1a89hpIgK`<#WS|VobB(fZ@Ogg|IaF!Reasp|33p5G~yAUD) zG&|`4I!zBW=mR>chcTOvg^`Jw1$^f6fwPAg90g$KDqjHccws!y4HpPG&;=Ndf-pJI z{TPlspi`E^LDy%1&feH93%Ux)Q6UR-#yDscof))B4!ne40^BQhywCQ8+)M>yRj$*5!6@`0{25J zc4JZNNz%>jz~NlfmNwMfFya%#2^^7z(kUR_*a_X(g8`)lLb|aJaHIv4wi4;auIRw- zT9n2o>Bj!R5w<9eMX0ePB(V-0`4_d+hnh=5Qh0>$GL%>BctT2nCdm66wYsz!7IC z)hX0i5(0Mu4r5Up6Hs$W2;2oY@-Ipw5^5|7&i#PHxu{KO(#?H=!?~!fNvOFb1j7zo z<{}SkkZ$Y-9BB-tJx#i?GjJG-(h7tcOG2dGz!7Pv{b$n6-GL(mqxSVlH@5*tsf#*% zLb|y>aF~la-T^h2ghVz2hq)+CSkjGMfFpQOnz5uCdjf}R|06eLp~gbz^kGBt0&@gF z!}yRh2SHnF1a3-$h73U?^hakLU~n{n46K7r)CNrwKnLOwK`)Vo8Tak%0Z?yXi7bBOzMMV)I$s^xxc?v_ z@YUfAQjRd=&VU4&1+W_D0gCkxj9CJorJ`^BM) z0|XvRfmtkB0;@D227&e}e#K=Fc<&xogJ#LW3|a;?2;`zKxC}Z5+CPcapv|CD_CX6% z1y*QqgH~jL(=e`yLY^!oMuA203XB3%K?`3%(`nGjMA(_$uz5mvP$)TM3w*%kB;0;m zstEJjA`R{U@VW=Yd<1AgiUI?8s9uwqLy_6>3uu;qx2yuA;}_7DY$fm%_Xp7QD6=_J zi2{S;jRyx91lmBmRlw7IfrJd)!vwxjQGwBM2IwLWh=DtpK+E#YnP!0IX;+YF;u5%t zJqQyQKuzocn|L3^jRZZt2JYz#2v4todOARX!Ewh!6axu*x`hqq=|7-i2jb}lHi)PH zfHtW8Ky@M&OnmW}+HO2Sq8qQkBW4LAVlF@gNmv2FDH(ok%$8tUz@lK~ED-IzLEs zBjI42L1OZ5VTM&&dl1RH0dx}{vpLfqQ1b2|(Zo6M3K7yyJcMIr2Z<&UPLDT8496|3u(-a0@bv~( zNCV{x$k!)GOpipw42eY4r zWrgu}f#l#g z2z)IvH~8vlP>+Da@dZN;XcY@+>m>tdF*@it9)X{rD}HRU1Uf-9=$w>apc~z1)MtT| zI=*1YQUskP!A)exVlk*=0Wu0?Bl-ed3Frbu#1$Uk4m4=JH4nrekSkjuI~z}cuBirH z4hy>a261OK^tf@v_FyD4z~^y*j;H~z#mjbNDHZt54_XiJSdgWJ<8l&Me;m0|!eb;e z+{g;hMIcHncA%?46j;DZwiyep7(mv8dnxXa4*mniY$ed1Qcy<=wzLwoo1VjwJ;|QQvt-V-y2(%g; z%IjHr2()S$%0pbP268BPk(d%>Q5R_SF?i+-w8Rj!5d*ZS5wv!miNhRxm=q6a?YscU z`{qmx;Eo>Xidb#}4n6w}`C_#FARas~tN`)EVR>N+h$jN$wSag6pexisOOrwA3g;ql zVy^CmUj2u$#$AC`K%0c6gLsTFrj9XgBp4G8?h!LNI6hbf-dw=TAh3a5kpaxrWM)ug zbbPW3wAH|j2_gpGN1(vC+?AI>ff1B+L0cC*L96lwIJv=UL96}Qxr3M(>zV36SAQk3 zI5;x!b2~CRGJ$r1?^R-QYJh+r{~4NtI4P;9F9$o^qy zV!^s-ANz{^b)t?8@MZ2U4B$i7Kzj~AajL-Ri0d*a&?vMc3%o>hT(kQCgCk^pH)!x0 zlvp^Fm_Zcyt|A5nW`Q-(+q6K3LnttVH+(`jX)uHK0Vsh>U{I3~6x-a;W&k|baAXP0 z21!DSXpSs_r<|Z$Oay*OfSe-G0vg(56leu)x&&n#1x9XL&>0S(4RoM=MxZ7DGqZyN zlM?t&bjO-3$feK>ilDQGSU`0@vjPj~nnTb*eGKm0s*qd@8-fR|k^tX@p~1u>uu2fN z$`@L(!;V^FQeXh@9snKQ0M6#%Dh_lD7kI(EK$gHq(2zGrmcRJGXc8h&yg z>?9=c8GE1|1b?PLPC{aEWC5@7a9pzrBmnX_{6s&;EvpVfj?Oa&c^iB#A+rLbH)yLB zX!8f7BTGpZ=++bkMsH~)(AcRXc#kLO&T472{T|Sj&!8y>kV5cjL;`!kqp{$M5ws{6 zd}0XNd;>Jf(1Hwna3pAeA8Z1+WCNuw&}tOW5`W0{2dRMCG$k1hP^L98sV>1EBEY$rAVrDx|<0zM#bi>{2376k+cdfZ|OcOJJ8I zsP71>7MVfaAFvsqb4U?W4WKO@p!2gpE&=Vxf^KU9Uq{LUswkKQj;ex-IFPHL*$z2G zz_pH}L>AN%(1t$nel8dv99R$zKeyw{dk0~~K6J}2?qaOx$02a3!Ql9o6H<Id5n%N+#vH9K{JY=gFqNzC&W2EnRWzX z7-7e42HkK4n*V9$0U5^NIAI$|1l4gfwq1mn2by$pJh2ko^aSl|J+l(j*n}3gp!@_W zoIqV5@RoT-H~6krkS=g*l-m)c3wA&p?r__)5Ol;U$Y~RKAx`@N7D08|gGJD@R|$Hx zV+qW>Nl^2SfJIQvTd@>s9%wTbB7HF_FbFhAfG3|p6}AQwhXSL(a!rr`3%GX;I_Vag ztUwI`gig?eqY~)QGPHA#7$Efw2dH*p6u>;Fh*VRspPuBz$O1i4f>DJ*zyMVFgEnLy zR|fS1A$!6=dwEdygfS^V_Jl$9t#YFpVMvY^g?%)!HY0h24jL~XL5Yf069XK$#DiBDB*!G$poFF11jP` zOG-f--$BRyg1V`YtO{;AIHEM|K_wAL1EgV(#SJr{Cfvt&J}@jKv4+E9s0l=c16C6@kYWPXa99mBf&6e-1~q}GaCnRD%kDY(3v?V1q|Yvr1uBmi6d>JoP;tuw={mB2j@AI3 z-vjE+3)~Y^U~z;T0|Ye!)P*F;i2o7_EYJgbp+=DGiudAhS3pl}cgO+{-Lg0m>5uOq z6F~iKZVLt`2hgEKMDM;}gdAPZ4ayJ#TQwl7j=;1;7KERoa13qyGbYv~K8BLraN2p=Q7HSys1-~JPg9gAu`;IRfE`b|hEDDSQ zPvt>PE@sfi5m16;(qIA&7l4{WhsD7iJArOx*dzgY=FA0MnZS{SWDc}vk20JC8nPjN zILC!SfkEI2(#k9r`0_OlXzj%VUA`s&qG6+v$CO~K`5N3{L!RR@1YGQ5HKbbd*Qt08CL!>mi8hWw|7A#ZRQf;&v+i^06J66%t7 zxC{ZGn2*&vhap{Vjx2$>P(xnhG6Z*+?3IPNWI5E3kGKrM?VZ!`fSm_5$Rk{a;0_ba*!hLa5Zo>~4$puKpe}hvx*?d!{u3@k zz_&dRnb`i}G6Z*+pr#Y(U@Pc48_>`TXkjU6co9?=f@YdPy-V<kQl*dOb-(tV-7GmPGBO+m@AxkjOpNVyuk@K20Uos02*OoP(t?< z3m#J}968`-fF{i#0n@>RVaNpV`6f6*<^;3j3}%oy9H3*#oIv|$nLSw?V0Sz1I10bp z2^Q9nZn-1q2yyUPPoT}IppjniSx+3?lo$ctt;+#B_6y#(#xvfqPy{?02XPaqB~D_4 z4?G)*Wgr*YKSysh;u&us-Vi(^AGi&P29-phA_z1q22THuj9H+AHbIxSfMSe++mQ#n z90_!!5-8a)J2f^mGzfr>O=Jd5k%4Ymzi=EhvjmDUaDfG$3}E1f_Aj94B!l;VfX2i? z3poTX2`VrN>=XyjAAo`ybY&V3Xi*46FRUHu03B)v&BtXs)_{iFLHCV-911EAm6$;N z2GG`yKL-vn2s{-5ZI=cOgE4|`12bg;oyZP8!4ZDN2kcHNM#nj4LF2#@3gCfZ(9H*H zzyhGAE$DPFf#)Kyn>|1|2{KLv8B)e$#vanmI58hGU<`Lh!vc^1Hg|vn12h&2n!7}~ z{{vL>D=<3Zo_PQr&Ime884)L-ULz>tLC3BOXn|*oL5HNXz|JdV0i99A;122XfJYKR zol_O$Xhku?igF{YDL2BEawFnNFaqt48_*~pDDi-2b3tVu_+CL~&>%c$CKr@4K{u6v z3T4n-FL?Epz(gqp22d{_G_47qJp-jTP<@Vb`3^^xzye{=ViOG}a4P{EJB*-JDUJe= zs)(ByGjN^%C_;i6xX#dnnE~3ph1V|vSprkku=)jj7CbTf*Hfr}8io2-P^f<)h5Bbv zsDBQH`j=3se>#Qwr&6eYErt4LP^fsKv=TfNuj0|P<&teMgUrC|N!~aR%)fG9ae{R8bW0BwSXxvFs{Y;QMFt};Sd z_Qwdi@R6k+GHc5q@D8+Sj{|hvJ?QvZ*cw1k%La9sgX1L7>Gad49AE%-oLL-M6&R)A zN9Kdti(oTg`te%%3agdWXsvdlw^pfPXcsLE?WKjGlWAe-Tv`}9gBFI)qlKZfX<_Jm zS{T|w3qxno!q9eF7&?s>hIZ4!&}Lc~I*AsBPN9XN(`jL72Q3VpLkmOuX<=v^EexGX z3qvQ+!q6UC7&?;{hPKke&^~lSjo~dm$e=Js7I@PlWQjBQJ_u&;!Lp13t3d~bf(Q19 z*Ruw$2ebkLG=K)W^aM2I4Y{9(N#G)QK^zC@f)vmS4Fx906AU?^{e~w%+w7%4vwx7i zGTfksCN>kUVwj);Hb4cu#|$(Y37YZZKyGm_0G*b^iPYj=2@+r>r^O9#V8dG6M?pq` zn&6=OJ{(Eu2VfXAWz7N5R?j7}BpU@k4hrTf#DPvk^#hQ4C-BpuU`E}!bb!H;ED!zx zb&-&Ry%lr>6i9$L55iIa&H-hCEP-xy+?`-h8dPR*JOI5Jp2?A=NP$sc0_Zv<@ET$! z#|I3c+sE%9lHLP`EP(?G3QUd%z?+qzOMRhp)u17A$8*mQGB}C|a0o0>1x-zJ2()P_ zFgUg_W;s5Xet^M|L0~axqczxk(5#UP12^by8k8QBfFd)bj|DOidCLMg=P@XNmMmZ7 zf_9h`mI#gG6`(CR64@8l|vWp!8critOU*MfqLT{S&l3Mmq1%9 z8Niow@`F3={8^5SU{UaHdh#OT5>iBf0ud3D;M)*E*B*f!z>_5~l?OCI!UCQa1g$bd znu3CE5di7OR-~Q7DAEkTMVbLxk%m5`!3|y?jXI=(WzLjQ;4G+L4PN+%l+%BK4j}*) zg0P(aA0z-eKaRNU3EC|M$^xL9%@`p&K$u)v961)0_~53Hszod3aHuu-D3t`a{$R5piMWR*aO!v zo}irS_=C}rLjZg<-v`+76lP2xK%0s>c?5Q{bK8Kk41*&Z=*~L^fs3H6fhJi3^P#K7 z!Ry9wtyt%_hO{+ddv`z^)<7<1f^5)XG-DD`0PXbS$pY=J0bO4!@RVBtdj1FLdf!r@ z_d5l8pHZOq0|k2DQ=s=J1$tjnp!XLAdY@3B_caB2-%+6VF$H=bP@wlY1$uu_p!XpK zdVf=(_ZtOzKU1Lh4F!5XQlR%M1$w_wp!XF8dLL1s_Y+(%v=abd7zdshWCU;1RsijU zhU~liDhO)%fd(}Y2dXea&I~~}fF0C^CdB|yBOKi9g)KeAQmsPHe*>Mj1Zna@?#}=< zc|psixydmCaz6q^MnI1GrpO4$VeAwc0lBD!A|oJoI#6T;tgMMgmGAEC$y$f5TX83DPYf+8azH=a;r1mpq^ij06AoqSyWCY~C7mAF4+`B=M5s(`}C^79CIc8AZB)R<}-0kG(zCe-g8x-lj1lJ86aU(6% z-%u9nOW~movmJVXCviz;6WDg}Ns9C3l-a%+!*-I=%w@_#{yErow7|2$U}u0fRDrh8f$q=|*ae!1 z1{XWfDP;Jl2a^?p0Bp=dAWL8a2WUWo1H7&A#ctT_8o2m^j(UKG(?REff_4e(GBAKn z>I0vBYQ+FLl7bmTf#%K>L9@J!pt)Nn$NDTqCeU0PH`L|uoDV*`41D91z;bB?l#O>_ zuYN?YIvLudx)9MG;y@CGwSZh;0V&^Ag)Y%^;xVL6Y{9x^p(kgde5!r*8CnW}); zd|66?*%3593Yu<(ZS4d#2Eo~u+0g*hDl-D@5@m8^E>UCxc^D!T%>-KMBG8}) z4nsvoS62Mn~3? zEbxRqgTQlk@By9>S|Lk`L4nbomw}rb+;9bl0%!w16X+UWNAUJO@X67R0+5}njw+zD zqZtJ_x#3fe;Q3x|YX$`dCkAr{&`v?sEEr1x&XRz$1mG+V2n%*lG;}&2w53zP1LD8q z%BaPFBg%G8P&lYCaKmPwL8k|RG(+c`uc|9Cy0SQc=bpjyWsIQ4KWO$D+#6tU{BRX? zY#c15aNB~;A+7;s9|lLpLQoFUW(H*sMhzwbM@G=9B}UMC4Di{&pvllzO#IvmU?G7m z%-p7s1Pb*7DAR(*9R+&jKpx-#r#Fam6__DgT?IgHvW4g}$W~%PBx}&=a%aR9m~ba* zCP<>T2X9IM-D?JlaR$fgEIt+nMkZ$Po&%OFfi^|>dDI>7Yq~&tCPC-yKT-o96pXwr z7&3wiO6Z93)3dywkN}_C2#axOK>~F4n{by_zI4%kbZ%9dkz22|{7x!qV zsBMMLVuBCzz%`4B?qNvV0q$XN%K>+Afifl}u)(!4__$H5hg>r#fR4Ea9a#$P6G9F) z1|>`mB_@`7P?H06+y;2^9hBY`n6q>l7+4h;xvdyL*U~UKGPqkYfZ7^Nh@&4Bz*knV zfF^Gl;fFPY7BvW5m&X>ipfk0=H6+-fj(;EvqrmAJl#T@+%Y%}GCNl@fp-j*ty`YUF zNOA`4cL9}F;NzS@i}Ap-(s%j}G6)<}0(*iZOJI+>z-`clhu}gw2%aWjH3aC8YET|t zgE(bd0o-O`0hPp{I))im4r8x3?BF*zg0F&v9|y(g$RO}kUWp0R2m-e&IKYb^K?gU1 z4oFr3xtGD6+YU53z$h?JS&6|Bbo$mW(2A}b;H6@)TM-l(94~+cIG~4ugTn=Mc&-Py z3ISzJ^rerNkXHF9fF=#V;RISo1v(}m3sl%MaD$p}pi)?YL13Pk66gpOP`#`Kjz=bN zJUT*l9w{&gGzlv)@iKBdGJv9z309zz5D(8pkm3PRQ$tb!X!(aD>;z!YS!dAQ;h?6~ zBRNPs3xF#k=;nGy8R&W+Sal3)T0oX3fbz8fbfqaMkU-502@oG#!GL0vkqqY_5=3%7 zVv#B=87VLc98m(d%R%ePKv$;ZWC>i55;zGz?#q&qsh-I}fx)pnONq%*0(8&^qavf@ z{DuY=1*S4b#zIKwf|gJ=FoLQ;27&Kvpzcem>rq2lvuz?4|Ey^=*aw?lAv=E z92v8$89_G%vMR6$%oB&Xo<(4{EZp@>5Z8lZ2if%?KC%mK9ijsesj1C?f=xN2yqDO6wr2aGg$k(MK!0XxRu1{1cmEls7^$<5~K40W1hfb zsLp95+1bLFC$I>ra}r59Uohqg%!BIegX<(FGEMRX=0G)0hifFpn;+C**4G~WKIF-Jyh#J zJPsIdF^I4n3j% z3`l@c;5-lZlj%($)u=<35~P!1kp(&l9yAgHJ7^1BDTB^&eFnO73OtY(1R3Cgq&3G2 zE3beW_MpBFhzafp3$*Y-f=hu>;E9^RRS{5R;Op8#heTlmi=YuUmLdg4M-%Yo0VYtk z1;rnznJDlb)U*UU!~)_FM28Qwg94`y|MB53`Ku7d1m=&1d{R>6~W`PsJu(Q-~lv2>Kc9fz);E}ungFrjz!Vyrzi`y2Z zlrnIv&EjKXUL6F3yX)o~ZDcGPWXeSkD z08#r*4N}wG+jw_B{26^zn)yoV5ec)Xs8cZCJeF{*i3vem$ z_$vo!yd6~eg7*SJ&I1I69Sexy5SS;xz)f25(7+BW9!S%75p+~HIABTB_X>3F5?G%F zBWRb7z;SuV79AF7cN6>e9Pok@=uIY|m;~h(T)P=Ta_Gn6fp$=VdadN>1s#70(u-UO zf=U!tMn*`#6Izl$ik?Sm@KNJ`@UxV6Dsx-oEstP&k;)(#^ROJZHE3)dxvvfG;DZLd zK-azqEaL-pwmB3*Ee22_g`=kp$}`|YI6*ZSwA4qhEe`X;l7lg%UW1M>gN8c6LwwLS zEocxF(xzn;I3^0~*E&J{2uh6LjyV$}6KJcH0;4uFhrnuSke3t~HJLdC+98L4gLij= zb~l1W&6z=?uHcy;NWBi8#ehw!fE$_$@B;yh(+Qdk0JU?o;A4!8kmd=u9wTEt$W9*6L=njS3<`__vqY5`91B2q z5-~`F2NOZ92nGcvX>Nbe6dGv597wsqMJWXaB}NS<7Wm1`3QTLAUNF=xhwQL}Tx$S| zOh*ZD@z3ChRP#I*;O0im`-0}zKxLrd2Gj_+|1z(CUkmLJZtE zq7|APK+y{6A216116^+n&Z#IH3qf9H(P!Mo2+Fpgh8n0y0-yQ{-MR=0hHpZ!Bw+<< z+(DBOXkV*7BO5-gU*TG@Svv`I!iRr&~zwh@eXK$3w&oB z6MTjOJUfb`sE4*U(aVw*Y_NcVPW?a=0iz=?XqueS@y_mp&@cm?rj$5W4VQ}Ph+zX=E!B=8B9+`TCL0}cU>;hFukVXwSDv4I$phAeQ;?GzoZV) zp=)>onmv|K08ej$?k+w67664YN0#G>Czl}?=0TS`!RGNn9XrrXV&E;0;CsbD6DM21 z7mk6J`#`QTgDwY|EJs>(a!3qToj`L3dL;y{`#?PIMf9 zQFh&8BgcgYK;c2MT}`m<`nakLXlQ_{3`l5z&kTg7F=I#`g7leWpf#8Vls19(nH;hO zc7ZPNIm3`8@Kk`?6l*I-U>uM1Q(0x4loBYaVwA|@R<)>kt0>OpnMAIEOBHxUIAUF^ALPg0Vr*Pe9Z!x zfP}>qqMk<5_Tb6^1_9EwHGuB8CSBVC^0Yl5PuqoSWclp_dD<3SC(E`8Eo5nXK&EXs z$g*t%dD)^8S&lqFp0*jFbt$AL1_JKTY2X2uSBp1lj_JKTY3vQF;$Oq(U z`#_$y1$W4DU8vc$7tSm=#o)CR$P%Drb)Y<`Eehul* zDliMIkcG8t^&pjr#m;KVk@`yaH<_5*lJ1hm$Gk1B&K09E50prKU-CP(n< zCFq!PlbixEuVsuKri4yb0Psv$e}^Jzu1sM9?5}Ff5B4}dMqQSjXj{1 z&nQU>r#9r^*h#!L=v6}C@IbN+n(Q%}wUE&TP!k%$0%fpH8CV7bHOoL9APz?rjDc`Q z#~APcxWFCI9D@pM6da+2wFK1v04=`--+u)fV0KJ^Xjv(!z~HDrl9oxJQGK`;&^49t zm7?$q1X;2KPN{d<0rntiS+iCG%i9 z4|6sEHVYtd613zJJ{5on1Uy;}DuU-Rpa+S8A_(HJ6AV~fwxb>rat}a(eS!hgZJ;B} zK>8UJ5upt^tW2PnA3RhDwFu!h%qbDrR0t#lu*`=%!REF(P`9lBU6}g>?lzE*Al+d| zK?|Ojz_B^x0I19)xleSEpe{(FMor!~q+!V$hYPXRI%`3d0bUnkv#SH1m2lVvt=CXp z*hiMG8D#02OO~$5Wa;W5OII&hy5Thm25wQaywPs&?js#*XlYJwz?4t~SuA zmn7?IB}>;i_!tZ>e_<;F{(=@AknF+(1nt5W8Vkq@!%h6;#Mf4`bZsF^R}UXKF5F0# zUA<)4wV9w@*wV&zL2~@H0dAKSQh5U&bOz0D%~*Pn!BJ7*zZ7T|46=C+ykM9?feEw& z6gnh`Xa}%hX{Z%Inj6iaR+j)~Yl8`kmKunbTe1qEDFckw1|C})QEb7Lx3H!6xnzyo z&LOA^TU`Bvrwc^C6Bg#+1{RhP*h6x#i8oSwH3hVX1aFCf&3zN#xpAWkzWpgPM0ywC(P zPX#(o82btnkPkr9x*AL@W=t&HsPoo%rYu3R1fB+F0Vf(2(9R>|jbm`FM=)kPF}0#5 zUht$oXuwE?L4lE<+i}aY0}PJGAfrBxS0*21a6I$;0D}PPv_2@0fCCcjA|u*={Z?!f*6<@ddc zkmRvU9p)K=TJ}S=%phLNKB$&?a4o3A04$7*OpKuQErj!u7K39wXlEOE$19@(v!}Gc zT20XAVFl)F1qNv)21f>W&`vN9X>M}{@P=|nF*g(gLjaAd-%4_s=2YYvD$FrQl=l+8gUgAypcIWj=XFi>`31Z{o- zCnF{WM$kpO;F1iK%OQ~iu8b5I1g=YhGbV`O5LhFxzzFKjLu!3+c~3ycYD^uVC5B+* zAS*UN<6z+Rav!!GWN;J^*dhxW>4EL41+5JOJDN%05i>VtZJ~f(TfAU`*A|-a0tn<8 zMBM^e?x!Q|L@!WNPpLHp+Jf^LHY zuU~)^KHO-Uz>WrO4PbPfJnsmDBgip4S&j?l9bph?1Wm((UFL{f>wva4)MY^j&KMo{ z%s#^4C?Npdr!@h@(}D4RfR;Oe~CJ<2ek#PJ45(XWd0MjJM3fbkxXvF|J$$-I{ffZCPA#UCV zFJVUHZ;;QR6&pXd-Ye-Kgu8G=?!!%nqc1uDsHvIJTs6c`-A z%efU896{^5_ltx4$&e+mUz{67$2zEv6OzR0mmIyz zTcDj^fe}<$hEM#!#mB_>5?#}-D+9mAmFgc+g+ba%~-X$O#!yaJPB z19+mz7`;O$a6%kh#ejC4f*2g2!vsJ*InYW8NNW^y8VHjEvY$bXUq<{Ql$$xS96ww}nudfFc%a$?)+ffQ zrvZ7b29bIekfCP-8F~(oq2~e_dOnb$X9Du_5hBBF0~vY_kfG-S8G68bsbMP?i1beb z@}d?Z^-Lf`&jK>^Y#>9=0W$PFAVW_B@;V!0!;K6*8_3XefDAns$k6kF3_T6VOMi$A zw*_SAIY5S<3uNf|K!%^Y#>9=12Xh9Ag^vBHVnwnvw;jf2guNKfebxI$Vk@>$P2EB4L36M93Vr_ z1^jySLEU%*@UkifM-x!bL;-p|j|GGS+Tsa2*lM{t(lTK1hyiG^2V|%NX@CyYA4MCW zBgz_BUuLd4H&N9=s$W5*`kA29i5#*8))1*4=AO+&s(%Ptz~PWBu!%_Z_o3?N z5vd;Lo+TuzpGl;8Sh846qWUdFs)xCM0g>uq?wL)b`s2{P^GYJs!}{~9h*S@A|9TSD zFCR1b5{93s`j^5aG#)x*-~3?kLT+`p7W^|MG+zm`PxTZvQ;3(v(ws)vp4 ztRqrAEIgMHsUGH@4eH8q$@|bNV8N$lKmzPOXj>KJ z@L%Zo$^{1SIkXC(VP^1c#Y*4_G#}8ws~MAr0)xOB&;;lOuxE(Yvz81!d&tnUj0`1IW}TY$_9^2{if0lO+Js2Rdx$qpAXfz;XEY9U?WHfNMZZT!U*k z1xA52qTt153QPj$LCem-lat`-Zs;rxx)tD4TbUs{cN7=}Hi8!Ja%2fC09_*uo+Txq z;XP=@IY*Yj3Su?1DS;<`1-1~Y;VsmLrNnA@2h}i(SPd;uC#@t_!!xK2L_4V+Y6H>1 zx{1_ycm;J5(VqSQ)v%FRPxnCmu$5R14?s)DIkE&+5vyT6XoWf{iSH%U4@AeqQ>X@_ zLuobS#0deSZTJIPYrv5uu$EX)--m`0(Mh8ZwDypc9M=ntxP`@5w)B&}DXiv97 zH4t40yn#B2=y>RdhSFwYJ>3m;648FxOllT=4fO-jiLV*zB%;fuPN)W=gY`MoNkj*0 z7t{u#3xSVN8;GtS9zyfOI(WnxfmUunx04Cn2W|JVfu7R=}rAgsXPsFS6{DDYcOfl=Te=$uB2EG6(6N8lAK90FTp z6c_~lsenf|K?}q{D|a9?mJ^P^XX=67!L128s0FmGjoCo~d?^QLwcS6^F?#3+;(=9) zsmmyj0v#1h%joQL%#-7=jjzG74PcRA6@e&uGQK4_dU~$e-m16$97P zI*`T&sOt(E_XUmcg4eWwhX+7Bf#0CD9*{n(A!Mxv{Ja~EEP>1FpanTRpj8!+!&tyw zUKZ%m8g3)dQex0D2nEn3^`Jvs1g@$>7F2-NJ6=xo}5_BG^I(WQW;2D?(Ei^l&3|@N2C@_Z~%9zd14Gmt{sV$&2*fOAl??Ly~ zGdVGWR+NC&ya?Q3RbYZ#CajIQM)XeeVFpKTfx}AR6^jDrAS<&$C;Nb}pkM$U7B27< z><~sI2TcK=02Z}7E~BVLq(5~~UInH732aK>EXyb`UrV50gBMg#feO<# zno`^fjNB%m9t)!e6X?JqQB;6KV2LWEXlc^|Z<|nI;06t%f)*4i zfQC3>8v#ITDm9oGvcToqI!!6C0%p*Wda%`okejKXTOm$zLk`Ci0WGByH~~6JRsnKH z6^H_znhjkci@fTU(NP6l7DJZD3mg;y-2enqs|OEJ(Dk#tr|#y1nwz<5LSmJOWGL{Yrg=lb95k6<82UyTMDc!37?8ktM`+xJ-Y{1u_`Jbi@j16t_GjN%a## zs=>9O0t4vKI8d1bs@*sQrf4BA{^rJBX@ZA*A%}+v>;|2>2dOlnOR){ImB2=WgAf|0 z;QDnNNGW&?Ga;3G;3}aGXkbDy^ao@X0Bq`3klF?&P(mSO>@JW}q8zZ3XqDTER=F9j z66z_?*&s+E)q&)x9U!%k!=j;z@r1w@kYY#(Kox^#G>}Yw0-4bO2iGQ$V#r(uD5paf zSc1!Z(2;#SpbQLJtPk3#ApqLXA#hR!wnKwB^~Xq5e+sT1I#KX|5i+^J0J?3=@c}4Q zl)&fH@qi8k24%|Qpr-Ew@Z<_|X4hq4;6pvq^??9Vc?iqw?=`p)wH-K=z(pYVz)sMK ztg!YLgTNeKSnJLZTBd+hGC0;}@i8$lfhuTF;juy*$r5lWD)2~+8=sCR$j-u|Lzh7U zRJ1cOFfxG(b{WtC-C)-%Ko8iK0j+l6<~E1BN|&L5iI0VmiHQNM;|W8Sz+_>N7D)RX z=?v@+MQ(0WcH02yht;y-F0P`mKc2 zBbTa=sb6p#kp z;|1P3hkW5E^5_A4JDVaSsHLmRz{1PmIA`@0(7=J?|NsC0vlqJZG6>Al0{3bdtr!?V zJK-2WM`lCYN${9v0Nuj~xlHyfuL1+;jvHthi$~=`5fqiszNP}C?gljYn+U9Ncu!1_9SU;L_PpFJHYus;I%rqqX60{ z4IQt+3?G5p>d>$O2kLat8Smhrgk8)5*zZP-lxfuR(esnEkS;De>$Ib|luv^RJh7BmyS7qo~9 zoM-VV2Wv%D4(+RedPSf_4ZfZoq~arJM=)Id6VNmQq)UWX1Kd4WG{6?9f!Ya}HXzO0 z&cUY~9y|!sp{_^Twh3Au z4~<^9YZ^h}5805Zf!f*uZ#0Gtm@6;}^n+%Iz-=g47l}a$bf^WWPXXR>&Z5BtnpI#a z$#yJ&Y)%K~Sb-(7+ysn1FA3WRNkCx-DD8mVKtSO)_%>$n)XWReVSexmU-JsU1HGX8<67@1&)HoBau4B+}!#g zOB_JDKm&%*b^xeve;<4#B#5<66x1F7v5u;8gWYa`n5SZN3;@qh34r%c8^9_<4N#rQ zjvNvV&>)))T9@Cz2vZ0unL$@JfG5plK*zZ#FgR*JX{5u}AE`mCHbJ)92V(Vn&;c?g zFcZPibq6K7mO$<92Caa(1CK7S$`_2tCeEmX7`a&<6tQqu;!*h+v_bg=TqQVsK*u-1 z(+c!-sC}UA3Z5I-*kB@zo*FoKm~bKwIN7vfZQ95ir`>JjXD=om;LS{}k? z?`cq8gBz#@I_a1hbgU1v0+YZZ&=p!>k!*0&0(4YK7HH%~ok4+tsa}B*H1!7>1Xo}Z zm@VeW0M0(3Q9l+(Ms5ss5DADP&~?I00u2ICb%|9 z1Or{|1382QRKak7gh2U2Bqs|rvzRT=rN|AMDu#?rfqGCJAcDt{$q`f>3T5dtf^H+! zXB3bYcp(6urhp7yg599N2s*@s0ptKM!69%@QGp4R$)Qa>1F*RqpndKQrw=kX%7W(# zAl)$R!(Ctvpm`hx&=z>`{bcZyqc8^eL1#}vPL6f_v*#d#<3R>O=HuyFfjeQZ;8Sg? zpgAVS97ll?M}bl$21llR$N&GC3qjlW9hvj9!5lZF009q%fWjEmeFq=m1?rADcFaBu zx*M7aG~&erndgB7AP)6Y4jds#{f_&jslRjN1WD#kS#*&k^%u6GsMm!|I)m?z2hG)4 zfo`5I1f_=wr@>wHKc}Ewbb%?n+}hAHby$?3+E9+t@nmrTo#Z3X&n>W%ok+D4z-kda z4jiH0@*Bm~kRe{j6Dz^}dXQ^DOeaQjCQ#0FJOdHu1&>98reHyplt2R);neWs&}HP% zbc8orSX3AkSU{(O@hGr>$^Z@p7EoGZQD6a095X1efX2wdZ4?#_CJqpnM_?lp19-C3 zk=cqtL4g509Mu4srUU5(9U{VD#ssRS!O0PHaU#fQ25v~M#4^7MS!Q8{^=uPRu^{32 z8`r@o4ES{6JWd6RE^yNW(JFwB#upOK*UDG6%tlA!h-32NVvp!Nj`YTuKf_BIJ>pOc{W2?=T+lA!hm z32GmZp!O39YCn*m_7MqcUy-2p3khm(lA!i632JYVp!OaKYVVMs_9a*?vs*Ms+l0CrU|^_f!qWKKB#NAtP=kFS|Q6V6d1v0Q#pQM%o1291M3iix^^rK zOiYkTRhBG)V~~^o1+oM#E2H-TnHeD$U!s-Tpz0MO1g>GB%|L-OYD!E3`#?*8{xD>L zYc@~|!;Gl{(Y^$qnF>>X7Nq_iNWBcQatS2mpe=yl8*2&r8FFr#0wcE?+A<=JEXN(7 zW2JiKKy7W%#cbd%KNe*#uqac-G|j+~Lx8Yh9gLXDuo!0H$U=l+Gng?A!{UJ(oS3Fz zu@iKOED;{y!ZZwvohPt34b(FNHBT6n7zHK@f)6?c#i_tE4sgl=U04bps{p4F@Twqe zs!#BcqIxqcDXI_ilA?MCNoF4<$?PK}slLxiio3UBbvJan1HNVvvK|t)&j_;S4%%G= zjf+8|hRKnq&=GR0ET|jI2+ICzM7cp@mY_Z}_-IJb3g5~6pu-_Gm{_uO85k5vL!;cF17evR9B(WGH|QOi+<6%s?<~8*pa`Kfm>75&9Dj5kW^la7 z;JBgtFznP&ZXM8~MMk9cvXEQ11>oygX4ilD;>S&+^Tiz6dQgj*TjM?lOr2z(O;1rrBsp^Oq-4Wxg=1ezBHt=U;837ZX8 z$Du?4bm_OidLq?rfU8r1_Rt{xbtOj7>8ao|P(kAopc+Nsh$_;^DcJ3xt_%;z&!7ah4A2lnUG5Gl6j(3?jhRDy+o_rN3_cQM5{bNw8}=%CIF)RevoK04-u{M zFwrWTh<0Z)(JGG+ZTnHUO3+j@D1CE)3MJ6WD@M?2I)SGmpm7UO51!GHCnpO$0Sr;b zq`(MK#^ku=!~q5rl`j}_vbaIn7NV3HrW7>jh-@NQogU~o9*Hc+2h%~#IDy5W(R>wD zE`t?=0i=P%zztR|fGRJ8%4M)(0PSG`&CPI|Ku799WA(ZWJ3u4+u=#)o3|Rs_s^CFQ zfgaEhzvB&tEP;jU-0-z{5KSIPa|jw)0=-Zzylg7_n)>@K7IAQy*9p$U~deF>K;Na^42E zEP-oK=UoFk?*UJi0H&r3$U*mpAxq#oRMT~^CeR8(OieS8{WO6wOW+1n(+#ku4#q5j zjTp{*fUIc?W0pWa)KC3jKdoWR64;8N=?1d%J}_hn+=SY66KoS`8`BmHO+?r<3nMuw zAO)UCmcVML<5q(m$CD)h(t(;BCa@rB>0!zeIHm|m4#yNh$)SY_o2C`W9sxwE~RM;NmNCPM>aGB_aiFlGs?#Lz^9O^ejIxwSz>BPf%AH)ntX49oxp!a>kBJdkxe zH53>GRx6?vCKr$c4U}W%Lj!F-IM9|bW(jP-aMcD@B(L0I$`ZH*%|o}qdFTogXcsPe zk|V+^tJT31HH-?(ZY&OequQ)R0f<|;fGcAtH zxmk{kg|6Hh3MjY#r;u@W1`Q?|4JIBzRt9eT>U)~6FgP-T`~X)E z=|(UpF|1W!aI7z0YyS|-+?bE1uwv50UgT(TBE`&@Jo?_8`?dB%>8m?3G4*#_XPD~ z!G#ax@)%8MvkDY#4340qx)J*u+7#jY8#)xZ4d5zu8Ge9DCD@(=P#dBb6kiMiCqc9P z4;Vn3khxJbtN}HoU>ZQ9b34Hr92c;G)G9CtER*Es)ItPcWp9>K}}G-wp?Bj^x+6Xa1q1CS(WP>)#y+~o$v3EJE_Xeb1< zQZrlNrx2tK4_d>DHs9x)eIHLWI(VOhh}N7cvwJ zDvclmE4badfp}9Nvk~opx5O*`LVURPKynT--g-v71NK1&&WMPD7sQ+ToOq=tq2rT8 zIN&((N@o(E2#*nO>UZK}>nZs5FQPI`Kk-p;lz6wkBR&ciVCDj7>4Q4D3Ek~61-_0C zdQua-lEGGQfZ8U^pjC*>8cZAlTa_5Ntsy0wK(-QO9sYt9N1!wLy5O-w#}CUv0^rsb zm;kS2y3SoD5bcoC`>>gXe20kAeO0oA(`i{33eVS240_Dos~ zGS-8}Gr*@tfSa6ZS;0fJ{4O%|N z=%^#GPE(0Npa*oo7kIxc9!0&xDC&bNf(%S4FghOC30~2^M3$vqfeCbl4Wr``kPxH5 zIUa7X<3aVHV=HL00*?T)vMC@Th%%_V;Heoj5Z|i?YAp%O0G(d|9x=qDXeKd=4#6** z!ei1wVie6H#=4zcu#s{+*6l)9gf0HAfG$lZ6n|HVQFINi2-JFUJOJ8BwOdw+!I9O9 z!A^m}v5Cc+(FW9aF=K*`?1?BafUm)FyZ~1VQse_skr1b=vPXyNupcXv1ZU7x3qRhxx2Qn3O+z_~{3A&7oX}JQE zlS0RGfmStv_spQa0e&@qgb1tIBfzZ+nK%P?5W!o~93jUU^K(1Cyazre1hn=QQ`HSn z(v(6~1-j=F+It5@K1-G(C~2T60vV;t0Pf;L6`g0(JvT2pDjOkQXK324J_q0`3D)UO-NKpb0fl90*(xh1IY)m7FK6;&{p?h(B>N^2M`2FF+lgGg9dR04kDic!i_y5 zKoJE=37}E{ob^C;CbYN&UE8?_GztP@>{f@D+(?6s3<~fXpiNBxsdUGwW{&`2b3io- zs45eH+{!8N6I8G7Tws433iEVj7fy93ck+fx?;*yjfzF zs1o=TJOBUF5GgI7$CbD9GUYK7$9YvJZN|7ZeCE(vVh6}&fbr~2z`z72J7z(+; z2EaP^h|5TMK;DL*aRSl#O8(xrsLW)C)DI0P-E~t=Y6u6j$uU6ASOf(fxP8A@9yHDeX5QlG#*p5JUwRLU zG$@m0(TGvEL+WsW z1~u&7XM%Y_6~{CZPnN(k5m0#n?rW+csak{F*90kp&G2w@BO4ZiG;PF_CD4s93|W;7 zs;U#9svXk3MOKAo)>QB&V+@CZ*N(uZo_LUs_TuKo>3#teWyp5=pt@`dC^|4*R)DIi z3%n5;!)4(0O4wb768X@S&L{xhP|YZ?P856WvA|*vl6Z9)IFuM2nf+NneVnzdpfV5K z%Mk_TH5O0<4^&NRFo7m$xw+*S1d2c{Do~dKX`Y?~GPwq~5H!yVz6+cYbT2rl5)nAf z3r>rU6INVdP-JxMSaF3xlbIm^Z0&I-u$6KkD;t=s89}r_mQy`wE*6w?!7OmW4{BV1 z?B&P;wG-XO&hxM1T3RW8`eXmAP51R0rtmpgXf@m21ds_ARddr zb0%;Nrobf7BM+*>KqD(mpaB&~@yG#gdpNQn6-aFgP*_Y=O+s zuz*e`l7KYDQI=eT6P*NuBcme|*iHdvB?d=EXuZb`>MiRs2spBV##=zi7*ZJ@ROAM? zHFX(u9BZ>c2?u)OiNIP_m<)qs7DR^48j z0vNhk5xPN+apZv3{75Z;qpF~A1C8*wLUxWi_8dG2nfw4HRt9d6zZDpr7=plUJO#$8 z<&Ml{pn6Ce5+L9XF=$4H3EKS;xGczxDaTxr?O2f|a7hr|x*3b1b1e|-Ku*;Yk&~@K90-8dCTMW_-N;{x4EkW1Y zgGw(LU*NbpxIGEwgLm75J9!)eOJp4xi@Bw+HDDOQqb;EH3SM0VYA-o)C@?y4gh<;k zFoF{@LV`M%XcY)vNnqn_|SKdgBaI3iNFUoq`=MswL+mS zR8aK|zRQJM9Fjl4`4`-a;(;{8L3u-g$&JMU%ZfBy#{CfCmWFy6x_<}Mk7Qs~U=(=5 z#EoPXXqE}mDAZtL0hd6aYy~R%K@C61CNB^RNehDjq%X???#s$CGS)lpSp_cbcdP>M z1cCNg1*Y?GLrnx#Ycl8sJ*b3%6!gltrTlSAg`-OefddfS;|5uHnu(iR5*i2sN{mof zIf{VlT5u3R50L=vWdX+mlfYpaZcu%!%fJ9FVnIFkts30mGwl=@LGzz1ASZJuF@s7< z(BSPF(E3oY7_?0d?Z1O-LD;G-1@Ix;uzn?IwH7!$A>AwRgaNqG2|8>QWWNRzs8#?a z1d#pzRJft8;&4Rtvq7adD8*oyaa0wo8e|3wXet5RDtHGq10>1}s$O964t57Gs7f`>%1 z-~%GA;ED@6DhsMVAv(Y_#*lmmt|S~49TmVMw9=q@0y3`R2v&+3reYu?BuX45N*$R> z98YYz2p-7g7GiK@a0J~R%2<}Iz~CtFCd~~}2|Aw@-fIG-Y6fl@aPE_EoctejoVo&| zqYNl9K-U7oBs09D&asO4AIB|)(EcR!Px;+C_xX=RbYgk z^A7H}fCiyJvz!``Bb>n6SOoUTaC1YQzylWI$r1o%6;R_$g9+j)4ulSY%K{1v0$((^ zA&vwkIZ#+KLysGWngr3t0yz^H5*DB$6tt>TfCDn82HvFx8o&S@DG9m@f*DfYf}@tj z4KxK0S~V!JR@0T$kpa@gftmr%yAXAtBd8$30JpMD73Lqf&?7Yrq1~85E$WbR4pgUO zETCir7l9xt=vvGN>!GWO6&PW;1LOhZI_ro$E}12=;HHuz3pisq-TIPLv##6_`Ld30lK|aw|9kgPYOdu^32h02Lpg4zP#HwxA z4#`5I1JpZd0yV&RKv(`ii+oT{X9O+v`oIi6{U2R;J{wly#Zc9v;L-uoGu;U?8{CzH z78H)0kfggzm75z>c7sb~fx94Opwbnb=s_tQns!0`HkeMR&;w`@15zanF>IwE#5cMO z3687~p%u_z0I6bv2(`mCX29~)VL6B^Ae|rB&^*jAK1Xmh&j4ytfE}j66ygXqtW6Q7 ziUDTjL1?K4vXTX2YSA_n>iMB?do;#n~T_RD;eqKqy9XHmJ@4VPfZLUzoT#Ep{RLG4O(JC|#6^MjnrSOQ913JlprAg6)1jX>*4P)!LM zZ~`fVHjTg|LCE~Ws@&WXpuQ9+eSp@ZAx6g;xJ8g9z+O^d;N}DevA}*Nu=Ox=*NJkY z@Xu**gPY|77eRMcnLzg1pr`<~$-ovcIx<2U`)pPWpqUe>1-H3iR{ddwvHrrvzB0qa zcCf)%P24b6D=UgscU0jr8{uZ%g`4%C38wEYTy{QOtO0J*G8Sl&2F~B0zQ-vINHGJN zI8$I2c&VbmAaGC}>~RG~ft8@66edqyQFeJd6+pXDvnzCTQyuRK}r1 z?Kc8Nlj5Q6cb>4Ln`7m=kP1 z=oEMGZm50Y5I(rtXUP)yA&ts^gvNi3#(#pwe}%?>i^hMC#{YxHe~!lgj>dn1#{Z4R z|Axl@fX4rc#(##!|BS}}i^hM6#{ZAT|AfZ>g~or1#{Y-L|A@x_g2sP`#(#sx|BA+c zEDbLC6&Tk#{by_zIHn4TUeMLapplSEQV>3PbW8xW{|l-dlxDI7mMelXJUBstD-+PE z>L3wNXA#^;fYck1av!XM1tJ2K$NC_;k z6>7p7b!dl3fl1&#$cjB`5F^0uhHPO6TM5%JQyn4?<8OlUVNO~g47L(9Dgf@nf|uTa zdiA;tJfMy=Xs!TK1R#wDfwh1#9jNwk1dnxsEja83=aDhBxu-1_DaSgZ=G2PVMll!c1i+~5iivcv{05_d3xT?Sgq3L3ivmrS4l zf(n4z9uS9sDo-BpDn%xULv%q^oh}2T0;9kTcCaBJC19ICLnUI6O{btW+zgP7sGx(7 zKwdzkGtgZg;DiYFr9d0IBLk#=@Zl=T2sX$;PE4Tlvl&45PBMTSNxBRyj!cD)jAiI% zK4*f;GdKzqIRA6+R z0GqFZ3Csowun25Xg9$7E34ms_U;-P^1vbJ3AQ9upBru;3>`Ktcn*x)-Nj_LK9u@;N zqrgX@33O;kgS-mnfD#pGs8bp&4dQ`Tf5JJej*M<_4jYIAZIYZ828TE35_3rf2GF?% zpa!D?qrh!Z1qOjF>M+@TLJAB5ht;8uf~7x@T2O$2TdW+g^a>JT6gbNTRt)ASFbP2H zaco#oo8`FVI)f+JHK5W)V4o7Cl?qk~a=8+UMl}?kDGJX4YzjzE0H`JeHI>1pC@=|x zq9`nfE35!11Z7{aLXg%s~An|Gt2Wq51Be<%C@%q3#E^x?agV&KUfHn)W zI5HQyf(=t(bOf(6fja_JbYy`86Kt+~#@stANZh;e`+@MwA3Jd~&!6)#cPH#OyEbIlv6!?6@ z!)iz|wMQL^vm49-@6cxuXp;fU2z-}QU=TQ<0<+~87F$jrYyoY0QD6}Gj760Se5wuX zsV^XN8&x5e`~h+Hsz5kDK%65`PB(~iK?R&D6&M|tfK~_1SB4c|Z`EL|Tkt-}Yi6)9 zpmfG4(7}$xIVXw4nZu35X^;f<3_-;)KK`>V#n2Qn2nF!`&1am2Zxd6djj$lqfFjpX$OAyR82<9><6Vf9EN6b%9 z2wy zVD5{@hZr1%;N0cU4uNi-dZ!9X@r;fqK(YdG**8y6WE(yoVsPXF$%5PpN%0@KxH&-9 zfDRQwh`!}RN|jB>oT8>WJcr~Z#Oeo4Y+=tiR`iO z$edyb1@MM(&qhk-`pcN$s$B(=U4AO!O43LGi3XB4e zMBvOP2v2TpcVNr*&dKySYL|KvE>SiGiI$i!r&+j zH~BWmD0w*d!yA;a+6gj>6)wB}$6;i>53U_za1?~g?rc25;HVGcvV&FuUk8stFgmUS znSluJzV0Ioj%FZL;HWz_2gNIw-l7EXy#+@Y9M#~87l3S#gmdp4K7efhD^NUxOF^*7 zr$OP3NEAyzsShFh4srTz1xmBgpm0FOX4)Xqa*eCAn`0$s)4KVo)R@lFl8FEW%Y&Kwbg63hb4u zP_O)*e}usi>_c#H+y=!vH{3b5LD>zF?Eiw?j_}H4Ginsh1aU#vTtd?7m#!lW zj#6-wcU(Te;E1rObMFxbM+La-)AdIf992PFa2J$GUfo$;Xidc+ z(8>sBb~AEwGdQ-a2Zx_4Sgiu1zcMuF|>U~z#xY7lyc z9E5%@4WYk7={HdNm?T8}50w86NElrQ?nC*%q4Yl}{R~RKfYKkK^j|3b9!md!(kGzi{fF{@Lg`ish`WD5`46G=BPjh8 zO235C@1XQ18Hm1_&~W<%6>nFCi2sI$>jG#vFND%7p!8-ay%9=ph0@`IcWE#&fN0R(KM>6T+J6ViIs&WtA^dBc5c&!` zgx;)vFpGcbx942k{o){PN=OlLM=s zfCluOcDFD2dV1rH9dp5QOLo2g_VL=yqpRwLc(SIGH^5pq*lUD71wBQ_A<&@*^zTfZY zSb71}Y;#(@ZFk?}6DJqSfgE=1;QCt=e;;dl0akeC|MgSHXFuwF2j=}fa=B&k!jIpU zgDtrF{NTpfpUzF03g%s(erNi>2mODaf{pB%a`EuOO^23){n|Hq@|$xTw%+*-He}!7 z?s>DXJoyW8<@xp93-=xWe7qlQ$fI{3XYFX%y>|sTz@A^6-`~+YX>JfG^qOXTI@q3vNns{*fwf;7+uFJn$&bL24J@Ek8>W-byeop9Edd(lC@aVMH=X?Kd+yHUo zhC?fU>|fV^{1^i_3xgw=U<9$)Km-Ff8-vr@z04qOPq(eU_C0AM>#qg5YUQUrt8TCOwz~+#dA{c8&nKOWANYbe2iA1=^zJ5_^dS-D+QKf!yQL=t|W=TeAl3sFtuC8HfaeqL%`iGEIIT557-a!#sVQ85Du z2ry(aFfh0>FfbT_xC{{fDh37yO(cFA0|V%wMh2R?tvETq0P3ze3<3 z7#J8d7#J9G6AKi|GfOfQ5*3Ow^U`xt6|z$+85kHYFbXh;!owM2uNDIXgEo>qI?!+j z34z?D2MP-ihXJDAfPsO*5Qz_pLt`Yq2?GOzDH7j|fq}ssiEqKcz+j2Qw_;#mutwtB zFfcIKBJu4Q7#Qr4_znyV430>ACk6%vXC%H0m<>r&GvR)L@DD)!4oZ8VumWK>1_lOq z1_lNX1_lOCXc&UTy%-o6ycrl6d>9xQe38Wc7#JA*85kG>7#J7=k;Fmq8qC1J5W>K~ z5Q-!o#=yW3&cMJB!N9-}i6kDyz`zjAz`zj0z`ziTBp%1Wz!1;Cz>vVez>tU}p2Wbw zkj%iqkix(KPNyI@f-oqbq%$xuWH2y*^A$)8gtHhJ7_u1{7;-@A0m+;^1_p+F1_lOD z`YA*bF9M}61_p)_1_p*wB=Ir^28MD528Id-1_n?X0+|iMRSXOa)eH;_H4F?4wMgpg z7#JAp85kHE7#J8Dk;Fmys+oa-p@o5gp%qEIje&uooq>U&gMope6G^;_fq|i$fq|ii zfq|hHNxYANfuWy)fnfpz1H(il@ktB}43ilc7^W~VFib@fpT@wzFr9&cVFm*O11LR! z+z!IC7#J94GcYjBVPIgGi==)Y0|Uc+XdYdNB)*7&fnhNN1H%#q28N|b;>#Eq7?y+b zA_D`%N+fYmdA6E?fnf~;1H)P*@pTLg4C@&f7&b64Fl_p1vyBHW4b~7+A>|tPF*o!2-kAZ< zf#C=P1H(}y@nZ}O496K57)~%SFq}jZKgGbnaGHUE;S2)Y692})!0?@cf#C-O1H(@w z@m~xK48Iu|82&IYF#JUl|Hr_<@E=qLF)}bPG9t=lCPoGZW<~}E7DfgJRwQvYMg|6U z5TB8OffGbSDMAc-U{#mK-Q&B(wY!^prOizF_`$iN`a$iSe$$iSe8B(B8B zz@W^?z@Wm&z@UmGuExl~pw7s^puxz%pot`|#mK;*&B(x@!^pspmYA87nxasWuTYel zn4*x8SzMA|RH?_H3#wqC^@<)N14Cj?acWU%YH3bRW?o5ZQC?z>LTXV_evy?zDu|z& zqEMPwl$w~Fk(iW|s*s$Yl1gFgpg6TCB{e>)I6qI=8NIT;ujKz3Uq#hDc&1A{dq1A`4C1A{G+xE&({ zgFPbyg99UI8X8hRg6bP5Mg|6FD5gp16_;n0Bxit}%}~HCzyNATfZBB+cR%130F_7# zFj_x3u^=%yv!qfXzbv&VEhoR6f#D;!00U@19;OBWg?Ucmg;_TGQg2dwD^8BKd+_Xd(GchkeuQE5kv^cpaH6qQE^71 zk*Qg6Mxr6ZHXZ>6P<*fB5dfF1i+KbXxIyg%9sve+P}?XkvjXOV^whl6qQsKa6qo=5 z16;ojFU0*Yb1Zlv;frow9ghG5GpL@0+H;*p0G!qyLhXA2b;k#&JUg!dxSh|)E5N|U zz`*dE2SS6Kkeyly33wfXIPZiOHbI z1%(TUSC(3onN|s6!Bi(F<|U`*K!Ot*#t_ZP8Tt9esmb|yC7F4psVS*>nW-torOC;u z#h^Z55FfIlEezQ zbY6Z5IPTK&i@-(}mli;+EzZj?DNZcOEKbWzO-Zdt&M8evMHR~}D5*@#%qdANO3p7T zDlGtIw~WNRlKfn_@jsycViSPGr4W>s6M*>JNI-xAR028)2r!6&`eFhC43Z2C421#$ z4C0`^2UOi00Z2S77l5RV4N!f>sl~;a`FWWspb$u9U{DZ*$ZHA;FtCF9O!?WVc_oSI z4p4q04TlWI^pK7KG#*nE9205PQx*%LZ6kQY#1vhfb*aenCh+gSrE3cWO#1C}fLL3rkar zOF*eNH7_L(6sXA=nR)4{c_l@epqR)_ECCC^1G^X=4Inj@a9(B}DE{*EiZhE#QuC54 z!7aDqVTru;{2RakV^Cf2F}rtM46HV zjs~cT165)vy?95D9l7@O1SqCy3tQc7U8Wtj z5|ay%6+^s>ECMZ%z(UYKPR&ct%u6jU%*iZC1qV`EF_;23;XrLs1TQ%$zX;3&6~x8G zka9FHzXX(wKqW#lsPcjG^NTWzQ(?XYDFE9EbviWW!9vBA#U-h^1x5KKsmUd&DfvlR zsmUd1g7Dae6*PsVi8+}imB~ew1tt0EMTrF&kO&6FSZPsmYEEWuW=UabYH4apW^r2vVO)2|@C>o)AQx4V3m0g5>!qAxOENDFn$o`B3qCsJ_Wi8dgRuhw9%7 zHUAitz77?CDkQ)l4C)UGLGl=jFvK0A!jQ5|1rwc>M-V&(# zdSQrv+JqtQp8};92}8_ZCk*k&KB&IaQ2uSGdGCZFV|vUY0t^zMaYYe`y;>p=cUg-- z?DK%~BSj!(L81tx>_~-*mx(~!-3g^Zg;acLUUpu7c^)KLgG+8`WdKhfNKyr8r7}bc zlz;N_OCZ%*VQFenWpQdz8K`1TEK1IRCIxUZ0I7tQCLkuXJOLN^AU@oXqSUm^yb=(% zAR{#=B{wxUDYYm+4VrGC6x@Lzf25QaK3d9v~IjGv=f;>oW1ob+>)hpCl&5%74aA2e+noILlvEHmqbNTQlnIMU%QEwlVMSpHgQOTFjupfNz~jEw zP&!Nu66Tp=khp6UgT(bjD7{b&5_jvwAaS}EN}myfr1=L>eLut?^#qeRq<)hShs3?6 zIK(_laY#KEAPzAHR)2_yLF%v4;?%^n)N)XRqByZEKQjf?YR=Cq$S6uI2Gs$1si`Sx z`9;N*xk>ps#VMKTnI*;fMWqD=sYS_&#i==|B_*jv#fd2?iFx@Y8L34egYt_?%JY*G z3o=U*b26*Ir9Y_ikXMqCnp04gT2z@^nw*iClLI#;vp6v)H@~GQBss&UYwr>>cb=!r6Pq>aYlYo37StpA%vs^;*H{*%$Z|=^iAl+cMXC9DIhDmZAWL&9QG&Q6BeOWOII$$Zz|a6zJs^vr3qlhUv;zlG zS)7@hnUe@=xk6-fDocwI-6(jFf*lKX4T?t)L5vaziJ%xts?01YPR&WnL{3JKFfK~X zPb*2yLoy1~swhs(ODQfb0yC2;OEOY(i&JyTQqe*W;!Ln2B=xAFSdyO)j)$bglpIha zD1|{nfI*Idfk93}06Z__CIQLskrJRy8w?DU5&{hR3=9k_Bm}^7Kc}JUK1&FI$DAZ3 z1sLQR7#J)hA$5bBBqTqFNeY1Hiz*}q7(nwkizFfD9g>8Y^HfrRK?XFgCM5u#L(`Lj zlow7?kh&rqO6N!kfakg2Cy)RchKqTI}ql2p(f%MTeySaZli{0JRaC@9L$Ehx!N ztcXucPc6-i&&f|t%t@}3J|{mtGY`y4OfF(zP?3ey1=_NZ z_J|>rZy^gQ!<}RyehZL=l>M<#@pM^8Um~G2ue>O+ARasblb`^qsle`aVT8;vf#v~S z85tPdkofM53=AGfd{0IO1}`MOHzNas4-(&(k%7SviSN(Izz~4M4`gIu2twiqGcquQ zAn`*P85qKl_~9Tn2t&uoBN-VOqLBE}j0_AhNc>nv28K8!emo-sLjn>%k&%HR35lP~ z$iR?-#7_l{IV17Y85tNdkocL53=COF{A@-Bh8!e*E+Yd&9uhyFk%6HAiC@Ubz)*z5 zFJ@$5C_&axu z=?H)(c0p6uDWGw<)Wj48a57XVODxI+)qLQ|-~7@Ng=A3EB`;kep*Xc9K_M-(sJMi} zu}AQXd5UgHPO)xAb_r#3jLCn zUz8hPT9lKT2P$S#bPe?kp(D{y&+JeT0MEsO=CeTK&!t58eEcCQd$fN4l{UgFk~n~%6n*-h2)nM1cS$~ zASz7}Dj66iC<=hr4}jx5uS5adCRH#{u(4IhRIpJn+@lC7yAu^kN(*vQK>=BuS(T~) zny+s_8n12yrBzV6!8F5+K?!08)IFe5JUg}0CAB0mGY8@%L|iH;LF$G?1$gZZiFxPH zV94-E2&hPeXfuTQgn=Ops*l3B1dr+K7NsWVr{`r>f#(&B^$d|xW{Z*lcupO(*a9>L z1mlC|(m>J=52C`0@UDqBJ0*)Tq+Y((aR=Ker!6qr0{P7aw5DtD39gXTOy za|$r^pt%lE+IG$_%}L2qFHtBc$_EYeDljlGxTrwt_>hcL1?bw9^2B0=)QXJ6Qc!)X zkd&I1Uz7@(6$Fnlf#wrH1zbT1Xk1wV-2aE!1FBy@c@V}2&G8#BI3789fPs7I1SXhp z2WTo1G$aT0eh-unO~TGapuuR+P%8FR%n>%7-*~<)aT61&jYnDGK*4E(8c}1^CpQo;h7~F2#0yP_+%EB z;8Ht96_O=0R0SA7OLYREe9#<-Q%-(TX<06a8Bmm8P@J2Y7m%6f11?lEaubuCi$MJt zNQsi3S^}~Xq$RPSAT#BQDx~@KUlr0NJfjL}Zh#DnPs+(p0y7Fg#ujCR*r4I3#GC-g zC{kvAUO;|MW^!d}9%zU+6=XDa1%_&nrlq$Ur1&Z*P0Gnk_D-$LO-;!J_YxTxYSbW2 zu2v`w8bSh@mYi6UU*wWlk_c(mfmmL_{(i-o>3NAIrA4WrF!M;vOUX%vw;xL~b5rw6 zONt6SQ$P!|$`KAL2B}7lrPPX&)I88IZ}BCly|>jMO|?gAkf!A`HAs{28$YEcZ--wM9W=5TKhpkY-|8rRi;q#G?Ltq!H-H6YD?7btD50f}P+4M=z;7v&ch>lWlBmVoM47|p;i z397zD1JW!`g!)rX72-N<>#d`Fo^M-r^TQi3%L7Gpa}_^YN(x!nh?KsYeKpPsd=Tj3PGvG zr8yY&t_y`n1jTh%gDem4~ajYk%3_W5`Q5h1H&RD z{$fT3h9yY+rHl*=%aHiX89~b|LB4}5e_YAPz_1EQel;Tl!x|+1T1Ezjbx8d6j0_AL zkoX%J85lMp@i#LvFl<5MZ)Id)*oMU4&d9*91Bt(rk%3_s5`Q-%1H&F9{$54~hJ8r< z{frC@2axy&85tN3A@L70GB6xL;vZ#XU^s@vKhDU&Z~}>cl97So6cYb5BLl-3B>q`O z28MG;{PT>UWv7VnyU57Ea0yBNG9v@S6(s&uMh1p!Nc`)J3=B7r_%|6D7;Yi)Z!;{Ro2VEBi`{|{n=DhOzPWn^MtU_#-*&P9_EhE+jrT69WSe5}%iefq@T+&(FlbAb`XdWP*2t0?;Zzi~_4b52Y;zZoXvZ z=Q)FhjX{G$LC~Qdh(<)8Vu2oHSPfbz2Edvai2BqewK%ybv!Eou2%;C!io2mFzyMmp z4AtvcT9N^(g27D>c)jaf1X|LanTW2Lfq_9pUjV%P8LA(P-7s%JT7S?^pe0f>k|9K2 z0K7z62oyKWkY(M%ObiSnOpxVwpyfoOObiTSOpsv@5MP{$fk6UEy(AL@gA@~Fc@juo znu&oy25JU~FU!QhAcv%0o{51$0VEGyeyGUAz@WqgSgFmV<)S8!|C47$KQ& z%*4Q8!US3F3X(TvVqh?1f-J8E@y(eS7%Z3=7`A})fR>muF)&ym*=G%MI}>D>3Z&ka ziGjh62{P;h;@dMZFgP$l>Ov6Tk%@u92}!>*69a<_C=5YMI6>PNm>3w`m>|o;LF(O^ z7#KW|{OifYz~BW6GpKrRkXj`7`Z6&v_#w&rGchm(AlVnl#J~^)l844eFv#s7KGeKW zCI*HukYAzcBbQAptx&BVYEgQPx|iGd-GiGiVj4YEWvo{510$54VX zhY_UD0U1busR9k2f=0RXk}F-oi!`l*!IS;YphYABkhws|66ksnNKQd&jA$4MfS1>k zV5To*9SUwUYoKQOXS)`Gma|_lg0vAY89~}zXm+7>1w$$eQmw2&V;s;?Y>1l?MFYbN zBLVPMgajtc;kb|t@X}VF{N%(Oh2WBWQ0rI$JT9(~QVQF(k(gEj8YF`DA~W;z$lYX8 zT#^DF+9(0rst+Fh1CPEjR2d6^wQbEHcSE2&UX$tU_rWB6C;PyJmPsPvx_-z8&S_In80~$(!@j=^A6hYfg@<8rMEXf3o z9fCB1J+7w!@fT>_l|o`pd17TT$ZMb>-P9Dg=Mr;M74kvzpP;3HPCI*IbD6T*fuVi9isDk2ZB=H(128LQF zu0s;9XJTMzfZ|3Z@g^n)hGr;kLGni{69YpV6t^R(?_gqJ=!D`fB=K%028JFe?nM&s zV`5wv~y2VH*^0M^e9oiGg7!6z@V3-wmp- zp?EKn_&z2EhW$`{07?8H69dB`C_aoNeuRmE;V2XzLlQsE#K3R@iccbmpJHNQI1R;T zkkZdtCI*IcP<$Rq{RJilhKo>q2}%4isJ#fqSCPc8F)=V)hvFMZ;y0NX7;ZuFZ6xtK zObiTnq4*w>_i;q^F#Ln!|48DX_2P`o3=AO5#0+V_fzlf@s4WP^tjrAHC!(LGcZ(C%4 zk>nMa85k6i_)5$S49ZCARhStVRFUM>m>C$t#>~KAjwElv%)nrY#J6H*V6a9~ zZ^O*MV2dPg$IQTBkHmLiW?*ncQt!mfz~GD|@50Q$;EKd|V`gA*M^f*>%)sD@B=5z{ zz~GI<_hDvW@I_MZ$IQUsk0c+!%)k(c#1CR-U~JFj>L~(W?+a! zQXj?4zz~fjAH&SR5R1f*V`gB8M^c}_%)pR{B%j30z>ti@Phn~KwjwGMK z%)pR|#Lr@8V8}*NpTo?+kc%Xr$IQTxkHjxvW?(2pQeVW(z)*}NU&745P>RGaV`g9| zM^azG%)n5IBwxkMz)+3EuVH3js6|p=$IQS`k0jr~%)roy#BX9|U}#2C-@?qm(26AA z#>~Lbj>PX^W?<+C$BBJr0oGcYViQon+kfng<*{3>P!hSf;?HOveQYmwBiV`gAjk0if=nSo&= z5`Pmj1H)z{^;?)37`7tGZ)0X)*p9^C!OXz06G{CpW(J1cNb-A_85s5=@%J$^FziQC ze}I{R;UJRyA!Y`K!$|xi%nS@ik<=e!W?(puB!7aLf#D<){}eL=!)a#7@e!bU_Y5-w z!&zp?R(lZt95VyMd1eOiRvZxj0y6`{MI`l?m>C!@Gefo-gUZt@%nS@ynIT)_LF%tD zGca67GVca61H(-u^KLOSFx*Ds-(hB8xQoQU$IQTRpBb{H9%SAFW(J0bNb--E85kZT z@t-g=Fg#_3Y?TJN=NU5t!*e9}zF=lxc*)GbU<0jxUNJK;yhhUhhM9rkEs}fRF*7i{ zN0R@*%)syw$-Ga@3=E%<)PG@SVEBp@9^aT57``Lv|G~__@DqvuiC%U zBJuw*Gcf#Th8&>)@;_)F7$Xa!K4oHIU|?oJ#19J#0|P4yWc(GRo{fcpfgOp@!NS16 ziNxn(VE~=|0x}kic~}@2c#-7!SQr@ik@x~E3=D!ud?6MF24N(=2nz#)C=y?cg@HjF zi7&yzz#xglmttXHkVfLmurM&lBJt%|7#QS{_zElx42np6B^Cw-WhA}|3j>2H5?_sl zfk7RKuff8=pozrSVqsv=M&j$RFfiyM@%30381#|&1}qE=hDdxP76t}mB)$m?1A{3N z-;9NU!5oQi!NR~`iNv>JVPLRE;@hw=FxVpT?N}HX>_Kh-E#IKpaW|lC4k@KMke${H zAKW0@#zEs!pf;uh3!)wF$il$j#KOSf%)-EssNj+b-l(bo-+>2S{h&|;UU?20Qpkgh zk0~IU&N-Fj4j6(KKR`~Ufvm#;H&R!-L&jitaWa6n1-c-Gl`9JagBuG2gF7gHAc=#v z!-Lie*ytMv6D>xGN;ii)Rr2!M}l zSZrtmKUHqE>9uB zwWtW@xNs!1BUl(1(8qT{yGx5wF%NIBQea>R@PaHYH!v_TG%zwSHZU5n51imq0i$eV5o6z}ux^d{8+9 zO2aUI6bod22gaWU7yFHOQau`Dw^u>^Et48sdQ$UK)1 zXf7LcBoUMkS}y_G<^z)l9o+;vvJJ)uEoBAGEl}5eWvR*WDWIJ#@Jgz~AF?#xm5G4? z6dsu23QhpYi3J*(pa{&*Nr_KREKtx=Fk*n|y~_d7OSxN%l0j+IBtQUs{F*H*0|V$N zHW)ty%BS2O&@p_FiAc)LDoQMmFG~eEJftWS)X2$KD9$L#%*zI~gc22UKzkO76q2E* ztC$2rmc+jZ5C9(|2U<4<3U^o?0h->lQqWO=kBoxKz(B}4$GSks+CP|D@Kmyu0>hj@ z$QB5gJaj*Z^AGY_+88Be5)1Atf^na;OG$cS-SuAjrBO3hPtQc^zgZplvb6 z(5)mX;5}@hq|U$-4Cxzy*1v(a^}+a{^=-&}&>A&l{wvUtTnr3w{h&2t$nv1|U&wsW z8ZKl$XgwA(A9M^EsJwyM4?2itQCwO0Xhl|G_Rgp zkY8L3npL+_0MDX>mj{63-vE?hEfg~I3Q9{9k}6A5i$OE$If=z33dtFzdD%LU#UFY3 z3a|_a*_%{+BLvd^g4qRHZwi{Tfbl`=J3)EeA9}EoLU~4N9%$w~xilxS1bljDX$jcU zQcwznCO<^nPJGX*+w1euTQ_dTHF<&e?}h!1Y}P}b+gOxKW2 zQ+h?k&|`TNLPOjv7#N;}Lee;Bod;;X0@N2sPc4EUG=&)+Nsxd5ZB7Cm?+4WnsxLwA z#;l`q^Fh7s;&|{uQ3_fLsC-*n@C-|89<=R2VSX+w0&NWg!}y@196`r1%z>8ue>ow?#=-cYGoC={hC=s&&kWHmPb|*WP0GwmNl(oK zcNvVqT?X(ucA$1pxB&PlQP8ofprcz8k@|{BEDQ`aPUY6&`86FN@@I!YFl_F(g7 zAUC{CzA+saJvWM3M}q1}b6FS|@}M{$ zNxXoCfuRtJi;%>NSr`~fptuxCyo`l`p&W`UkjAhoSr{0qptu@IyoQB=p%#kkkj$xP zVPI&0;zlI#CKd*UW+-k!GN+Y=fuRkG+mY0FurM%mLNSGT2DE4kyj>9G@Ilz2ltsn% z51_~8@kc|_0c4LgsKzKLEzUq3U%4R)(%uIhM+(ZzXzD$5Z?qt|eLoka$+k~Nh1|7?a*9@55P&b3xvoQNX$G(E} z`X&}Qf{(4UvdT-XD2a!}9dzgpx_uEWL4^UI)S{GB@HwQ0Ca{A@^}+V(6%~8L3V@G_ zJ^>oz2kmbJZ|a4v#RVN391GbKl$Tl#>Q=y-=nQ9KA^n9e76yiHq^pw`T4qesi2MXMtUaTS~{boqyXNWV9<#d03QbqO1q$WwY1cdhYP1ziQufhwTFBvB!$G@W5iJS4tX$3u<;ftd$7S{QWH9gGj!vjsZ#oI?MAcb(@Z z7U&x4Swgp4gGR$ZH6W3=DIS_;Xnp80I1I=d&;{EI{HfWMP1(Z_t)*Q2Jhkl*bmcFfc5E;-yI9 z%UBo~mP7FhB=MCj3=FHF7`Db4baXi=oXBm9AjU+oj$48wX-OiajsP8RZ4Wx)9LfhB zxeYp+A0`i~=X8+dK}SVX-))F-E6}p}cu21u>`sRy0S3@<_n@uipn4R>2c;`;Um>F? zH7zBx7<2?i3iz}#28NSK0^qsWvq_Nsn^%({`3=Dgb#P+c;FzjbxU^svzc94aE;SdW0!+$6^j5Ho{goT0OC@7sm zk6t-On{vM(KR*W?M<0?QX$f>h9_UyE(AIy?6ovdW&YYRZ-5R4DHjsTh81>Jv;mXlhco1C9hnwyuR3*uzx z8X6cdFc_pl#_X(9A$x=!Qz2;$oD}0hM?xtirlde;b#?6&5>g>!X3mMAa}z)Z9~2iW zB$pO}4mJay=mMHQgmte$M~0*-=z{k9rj{sx+INs)u+-fAqDlqm`Hl)n`Jh`rKqGZ! ziJ3W|jGzcUKT-ia3Mi9OB@RdAV)Vq>Ui)B4`@oWv;cGr zmtJTd$XTEkXj&$y`IrYCg#jJBrjVIpTLL;J1a1fD3I$L*3}z?jDg}_8Fh1z&0%SgD zo(IH73Uly@#IU2}K_0%6203;nH!(906n(moF;F zK*x@y7G>t9C+3uRgTo4RGfqKvx_)MEx_(Z6dcJOPVQFGfs$OwfIwUaTL86A~ko`v{ z>5z0`1?AhOL*gH1PiQ(M{bU#+LKG6;8OE6@xq7J;iJ;SZL6`7=HpwS~x7lPRmL)xUm9IV@wy~dYD}gp?2jYCZ*=2$05l@H2*l-pq$kaGfHG|VmW8IUpMq|%a-{Ji4Qq}?;^q>?;c=wZ4H zFtZM2K*AlS_e2Jyjie9^)~1kDgs3Mza6`%j(1|#Z@CX7g$WX}0&rO9{06y6|C9$ZI zfk7k_5+-t)khp`@H!yQxc4}rq#>t_kmE=Rp!~EP-g@VNNR8W9HV+c7BDu7ECm>JEP z0t}#bbV_DfS!z)UR6PR&Onx)e4Mq7m;1h96i;D{~^YT)Qbd$hagcQKGq$Cz)Gca7p zgoN*vOw_Qsl?h3c#RZ9ZWtqjLi8(oyx*3@%DXDpIdnB?T;pdZ|n39>7uBWH>XilpF zZ0DRpaB2yN@9XBM;0n&`DJh91iMmO}x{x!SltCTi%w*8%M&P}$sc`B1^z@w6-29Zp z9EQX!$UI1X79`vnp!~ipNSO+Y+dVkqHV9M_DTMfk1VF8G0UcAB8UQ&69+baek(mNI z(6%=7gt0&cIdh&&#P)&{YV}%*j#6%}fU! z91ki5LE#2E&=FKifwriDPBKw|l$FSaA`FC|t_KftWOX3pKpPkz&FxVDIm89p9&$`c zK@JX>GFT{-Cl=*p=B2~K{cScRj)@J2KT!1`YhY&k<%3-a_FNG7GBHq(EyD!ChRZ|h zQH8{u%=A3n%#zgHV%_4B#G(>NW&o8ky5RapHz_}*5|-YZb0EhXmP4vvc=|k$14$zV zmAb}|G>=;L-N=EQjS>o~kU(`JB5aF6w;H7D8pF-v$%UK&la~)Zz&sIjeq?G&u`ZOC znV-kNpppwI17I}FeR{bNdoqf0D|Jl}`7|jPlJ}q~6BJz8;FDkyOHyI!up$?7WFxWR z4=dAP;h&va2{IRy5)|}7387rq)BsdEg0L2SY3&4rxJ;|w}|DTe`GexkRX zQH+9~>JK#wTB16GPsxUq{E+Gt7ABE-ka99HC$*>qOela!sFUF3Qb`^p4q^H#^B`xn zIOZvUcN;7CCnuMJ78QM%zjPO5*DYAwzaX^;GV|x@0$N{mCJ$1Mz}gF-eer$_3=D4Y zD`}uZ*u|*|pt*{?5(UtiF{#BR0sg@u`elatpu`8s$@=lB6_68u;~`2xm0D_Ei7sfw zC9wc<#xQ7CFX#|&Xjh^nU!gd)L?I(JF(tJK)|P{v3k2Q(Q=toKD(L1HWTwE|J)r&R zplidhxf9md1J|{nc0IH`7RLm+nhf35kXsrM?KaRpV9*t280x@xWk5=2NRfh6TtXa) zt8thDE?xDCid73BXEuQ589-N%U~_*#IjEHjTAEN?g6;-L!N=u8$%0 z5SR&Ws^p}mBvry{576G56wvupC5a`O$uLpanYbm1p!t#13SC2R{i2YTn3B4r0FoAk zxFGp)eF3D*<12vlE%p^a^6$9Lw z9aL%~%DdCa`6a1E2s_UeLBbi5P<3Hh0^S~dQv?ZTT>gQz-(cYfQ-@wQ zLd}OXNFk*mByvEdF}#$=pP4|1Drcuwg8S1&#gLJjyjX~W7ny&_}bA!1P z)<1*sLD$NGu78B|LP5Pv28NUpNZNp@0bSn)%HwDbg3Po+PKC}+t%P{U$_hGffu$X%gSi{lZ*zg3+Xkay zcEb8?uyBB66j&=1+L%DeG2lXs0asZ)u?*5KAhxWIFNXAq36<5bc!8M@b3d${1hunJ zA{JD1CuZg$mpQKG&~%<(4sT;6ltcQ~sBOO>@O4?bpn08g$QoEsJm)6q8pG_JQVywG zlJj%mX03sm1#2_H+KMo@!{P*H1}v08JwR}KtvELaVlz?Y5u~8iD=KEH5MTi1S5N4* zwJ6aAF;Lf`0+RM%YC%_Lg3g4%q81#%Aiw8SK*m|1^#W)>5SkLfX){GZUEO{{1*DC- zssd8S!qNq-?uMlUSX~VZ3s`)^!U84^<3sI)+J|r@s7@jfI_2ORN3W<@p%PM7gRZCr zUDXONtHVJjRVhG5@IpZ6DuPdoR7fdJ1$6)!A}S$mCQzOL*{7Qfy3UG$0cIZPicwH_ z!{y6B_h5lrxw>hosVShAPbTDU95^55zZI3J_56`aNZD7KlUb|_)szV>Oi+CdjuxEx zj-v{ak6__VsEs642`S%T@qnw11amjcd|3Qo&v&5E0_Bu+U1J6GQW1B*Y+n_mj}I#s zVb^iN?1GhxkZ~?p;SI72-1JNVA0CzjYI}mlxS)rAq%tsQRYStosv6SPfcXVhR>JZl zdYPD)TCNL=TbP?Vpy7q?rXcWT6yVwf$ z^$_}@eLk3*e^*1=!Z0_Z*O9RL2yOtRAcrI&#Ly1@tOL3!4VHO8*CE$H#^pif3UdAd zjp8WerX^x&>@Y+_^?-3$O890A`c zs-UX?tr1I#Disnzcg#hCny4s8j4C7+6o4-I0A=8$RKzAO$k9BB3gwBF3ZQF0K->6> z6@on+4RsWX5Qs2MmaUbUcoaBtN*5Anh1J zY126;GdWu!Bee)z%tFSKK$QwOJwcWbK*tK83qcqdaF%!8HITebYi9^3JZ&xdPsW!k+C4(X%9Ym%Su5{ z0eyVzRwE=`zk<^6(I}8jy3mm(-OLmsECr=8n8ge*e}U#qL2Exyhr>XPW!S(ObZiV& z0WN1i72|ac=%P$3sj&76uiE3_Q({_GxGyWS$v1m8+vr0O>##rGn1O zhIFA4L6=KG=B+_RPCnAGBqX1JDh}|-M`B7Y=$h7&BGBpPdI}%r&zJ%#5OY&>L9Gh~ z@SF|m`1QnQ$oLd2-NDi-O8Xwt2?gJfssOraumUz;q>!7WYXt8@JZ^@>Kd2RzRa#t< znO3O_i=EsQ_!JXdJxdE@4hlSI3mv+J_S)cTOj;mqLm$x1HwwX!YhM*U%f&v5FuS1RrMEgp%6;eJ2 zfbRtYb@xG+mw;MZpdkxTYC`x|Pfrh27{kK}yyQ_AeCH=9QjB5c3T#dk7Qe8$PxP@S zQ2GGRutH}^^7BfH@^jElRlpgopngMXK|H9P0H5>y(F!TkU}*|gCPVJxRRCSa>kPiz zS0N+69F&H^RcC676=->bZfRa|No5Y`J|dWY*EUF9tq=}AT7tlk*$x>4^@Xh805w8O!Ph}R(k&lpbI5$qS#DMg3~>8E=aGT*0G)AZ zVqgMlLno$#Hj9C#@JjPiJo0l>A@yK{})JSd}qEF96@A7L*FPOaWp=PBA3XAUsGu=z@&j z733GhL(IS)moWE8Ffu^Ko*?5L7*hfd=Ae88TT6jHX9=qZLlQxaRd7*PlCPkk zr>Cb7l95@gP@GwkssNwI0PjnK)=DMdMbAYF1*t{F`FV*s3YnmLRdT_pTh9};mJX&J z>WgBmO2NrGBUK@-6uhXQ9BLbQcnQ)rsmw3cL%0Q0y+RFyZf;FY1+P;{%LiS;398*l za1mmUB{oe&xeXHRdKt#x`cWaRTsJSjC^s<&QU5ONfvgV!okpDs={X00E+B%qAG|UE zG}H;gx;g1!3bs55-cNz84}#URFd9~e-RgnlPpHAjO&{?6n7HC!zZc>*us-k|>fpE! z&P)fbc>~pW(8?1k0!jby84ko$Oi?Q6GVU@^^nsEl7KxPn42H!Rv59 zHX_;#&`a1reK_dNP2lx-kTp7x)RCE@pk7_84w*}XkP5jakaj6}aYa(PE;s}r6+&uW z3cM~*>x0w<;O1*?DfmuBSa`(lvl2EXevO z-K6}IlKfo90??h_Nja&YB`2U|_L*g=aDNH+L)y!r(`r(|gaVk<1)Zx?07`YB)s4Ct z`JfeApy}F@qLK^-28MSskg*Qfn7y(Gctt=7D0WIx3Umz(bqov)ixTrv@^e9R*M>R< zhNdNnNu@c7MbONjSe%juD#bxlUBy;b1)w{Rb5dcmc_|9em80>X%Z0%GmG%9Qb(-iJ zAaxg}`Um}xID@TW1Kmttl5fQzF#%G~*g$iRLMliGv`n`&uQ;{DE+r?W1k_~#m9MZk zc9{V2FYJ^f(3nz63Uobzf-A@X$d!P;;Om=Ws4=8=Y^uqd_;QAAE{{?hCBy4?v!6e97 zILs_qp9XzA*=7=?p8)H6fqGD&@oMlQXS8l(aB2x?Cv`C_%yu&{FoZEMFn|U~AXSaN zemtlV2I_hx=IBEkYYZnQLHahACqd?>a7GN|xCn+HlOWeIRzTwf#-9P@!y5nK4NZB8 zWqFBZNr^=Y5K1?-q98FZMK?DECIFdsOVH5w9K4ThpCV>?*mom2pZu5U45Jd2{%|cz{**exh4IOwa1_pbNQtu zzMzG$6QE{+n+W-(B`~$HJqE$4iABj7pomV+KwfAK@)c-Z1}skYOogmrf{l;D_^>!Q z1eJ%Ge_|>m4q^E_zqBMLGcOfV-GlrBy@w6fc7o}XnFbjTfrUS;Z3G(!hpB_Cf`T<$ z5M@r)G)UTjse`SLg7IPF+s^rU;Nf6cxIo6yLA5EQEdr_M5%tKCX^{Kw(C1s!Qxsss z4>|ei3i+ia_MoNx3gwAqpyqCRett?)Why)+f{F}Xh#Y85w`TR$hUwVg{}E zgYiMv4}->O}zqWQ$|@TbSAABN-Ka%fXrgh7;k2N9@L+p<_>&aO~Fh^ z-4vN$st!J6rvyBn59;-U8kL|`q@b=?W-)lXfFdIF3QBWw6jH!f@)jdR14~njDixsC zgZ4GU+MlqSuQK!V!V@z=)hK9d4ya2Dbycwf$X%eWLQZ~Sik_ZcYHo45l|r?ZeQh>q zg(`#z4`a|(;h?yQ%rAwW4utM-P}>U9u?B^gBBF-^-ctu|pn*nzksFE%p?SrrC2%`H zcd|k4z#cX@tpEoOs67m_0bw&(7<#KKNCqiTtQ3MFDHaxZRtgM!vms?6vJ*iKY*;!2 z-E|ekzyNPwAff@DP9e<_jFip55HK4u=M6Ipbf*<)pDv6Kx|a&HZU&Tb(DTxg*^oLA zi+xa~3eZT!wD`bm0S1t{Fnd5}mVxXgCf7sS-Jn)00|U<-$Qpbn1_lPux@wR+!SYxf z1s2D23Pb1|0S55-Lr}9q85kI(3FLPLuwi;|`%^&q9CYpt)QnnaUWartQ1c&HD=3vC z%_)DF16iwua5f|hf%O-IdM{|%1#AdLW`Vm$oe@&jz|PV_o&fU8hhB#cGS(h!11LE$ z)XjzTvmo;q;OqgagFxLGMX;)35Yq~(8PRcqj3I&A?h2&^kooT7{QNvUJv~JHfX2T- zeG7Q}=rb_9nF}fNU~ve#7M$2L02!-*qyd3>h%^8izXaI?Tv zAqr{^%sfz=9+VDXe9)Q@&{;NcpaJ|njFNd@kPbp8(neB<`-qAXXYt_TQ2F~0hatyP^T6Y zsrImW2oOgxC>Xj1!yl{#lsI7S1Ko!Tx>EuX#`+9f=0oZZL^u!*?cmDdlGI$ZiU~9c zSd?E5YD5?78Y;k<#ksmh2wrZAuCW609vRLBkbYruVo?fm>kHI2hV*udONv0}7^J3v z+sp9Q6sS?J3oW9GA?+zx`>9|7WSt+#Oz@^3WP?!+faFAob_SUKjSC>{FI1(Fr~)a4 zsk;MJ2Tm9Ykhm#@tO_ZHt!;`2PpKh77hHXSs!W&y=nmF2&>4I%vG^kJN-ctVq3V#0 zD9y{Pfc1aDod6gIa%Nw#LP}-|cvc_0h6{g*4O!|P4>B?y<}^^Q-M0{OPbFwSJ!lMj z!a_(L2i_9}UXoO#5So`+0bgl`ECDi20cIL__!!0k4+<5hra+GQ%E?bp2bEx%c_sM@ ziJ;@5D|ErF?P5skODt9>PtD0u09}28*gjLNP+F3ilUW7Q>Eq%U0Pfa+BN=I5#Qa5& zvJ1ABL}DSNZ-u;C57q~P$-(ATVSHFy9Jc-sHtq|fVePyft&qM0%r4)BsC^umxiIr! z`k+Aui#_;wGy2#EtSt|V6VTZ=pt25s`&fv=8rFnA$^+<^OrR!fO*$Vy&I8XcaRZ&MhStF79EiUe7#LbsK+4*apfgOM_nI+)k%|J6tuz5+)4bOUdda(Y{Q3eJEM+OFl3bgJa zYWt!nKPkTi)VwIrH9(9F>8^z29ax*gW+h~N6IQ+kuY`={2Y_dLQB8yd6v#+~c^xYu zc@kz`-%3bZ2i-hq_aD8f37?CCsfYQ|lo4__0!mncV?u$5kV5n|jxaEQ@5u%CS*Fe?*oj&K>0P5o- z^n(uo1Sv-7PfRY#FD?d;C4!nnd8s*Y{o6s~2@H;3ZXRObZgc>hFebpjzyLa-6?8fn zsO14#-`SJC9Ju`n<|lR`jIehK&v zN66$gBuyZvT9tK>8E24tKw%7WCMaAJbJDZ2OS8(evolkYi!w_}DhrZJDl1Gut=#J% zMWEGw3=9l6SQr?P`8Qb@7|1>O40Hw^_zWYoQ&<xhe#?`nWm< zyDIp*DR_m4D11=2dKf^ju-) zU14Hi0Np|Ya~EjQMQRbkSuk->Ry(l)GRqDMH&B>?@NJ}U1Kl2r-))JNpkZ-jCy8tn zU;wQ)g}DcGvn*aSK+}7P;00Nr1d*5nKecHdVm@bURU|f{lV91H-S4kQN0foRITz zP_ScaVoo|Z7niv@XO~o#7N^1r%$!PvlEn1%)D(r(ywY3+ukvgL%T16~wmO?2H6*kg zfm!TTo^562>WobkWK&*pab`Nh9H`!zP#UHgeDoy3)kYgOLEP*SY-DN{1R`8P1jDUO z5dU9=(ifmK4s(ouK+S;^Sn!ex>PWOAFcsA4RG@7EVP$S$0L^TmGQ`RXQglEMt!3D; z8B(Kz;)(})6W<*c28O#V3=H=`H=u16U;wQ^TDlq1i)UtFV1ThP}qg0901P+^Io-cbZ-x(w(6C0On2; zy1UcVuwpxL;R&kWVeWLGzdOwpb`a-IP`wCqrw`rTX=ZeSNOywjWtcl7klcA6l<}bL z-3Kh7n;?rpMBD>-Cl&u2i;!eJ4jB7FWD`Ca#B33c?Q{ZfxABonq_>j8?qXK!UhebsR}w49?LCA zB6}cxTi7i~Fh1-SBp4rd3lfa~3VI6?j1Rj73C4%rf&}BkZb5?aVYeW`_^?}$V0_T5 z3uqMrj1Rko2*!uqLImSGLT@30@nN?R!T7Yig(zV!!HhUlH?X{mlg#)x)1&x!y`c2>)6hJ3VBVDt0 zV;^Kh_W3@@NFI0|HJAO68C94W zu$3UNVh7)?Y8gLuXJn}lI@TDp zJSwpyIRkvJ@qzsU44~1s(@YEupz)|LNMZezg@NH43j@P<&A85kH@85o#Y85m%<|H5wlMK%|7t1UAtWQ-1^jfItgft3|; zn=%_K0|PrN1A|XuRiy&t7UJYo1<)3zf}+&2%>2^goJxfx(8iF0{LJF~JkXZP0|%&5 zzUAj7r^Y9z=H%!a>KU5CuUtt2kKKJa04d+zf^O$#fSk%s?if~aNeVbJiYtrtL6*?v2<`tI~6yz6`q^9WSlc-SXprS82L%{Fr$>NJAOhV+6#(`*cs&sVjnWC| zDiqL0Hoc-^#}d%?Oz`E;`Jl5}KzGU%fo?K(flSIeC+6gUlqP_VKq*mxMLzh9_F_fI zo;dJ!xa7pr;#AO@&dj_t(18Z23OV`t1&}obpql`53&0B(OF*_HrXY6Z!Q7&doS2-E z3f*Ow30kC;otjgr0KOqZQ3146u{Z;~`xty79O&R6(0WIZZiNIiw}NJ%)4?7AUCW%D z3fgCfp(p{gg2L;N00Zb&ix&q47?Kzm81^$l#<@6<(kv${0|OT;0|PfJ0|RK-8swQG zNX5)haTrqOfZB6ui6x0S3Pq)PC7@$epaaod3=C5aL)v324@1f&NX&yab!MlgfQGyj z%0WYUd7w0~=P=~70+6>-QxrgVhLq-%;J?Y4mz9A5Hr~U>%0P!S!@wYO1QK3qObiU5 zlL7@;8NfF-fbzT`D+7ZND+7ZtD+2?vxCk0w6pb&2rEC!gU7H83A3$Xbs7x=)1f8~1 zmYJWESdyAzrQq)4@8swc@8TI8;27fU0iQ(#CBn?aoXjfFZnf03{GwEtQcpk65YQrr z;?xovWiXV27<8-QQAk+~y1@l>TMDwjBv=_3Bv~04q*xgkejt^_(yXXuu?#B%gDfip zgB&XZgFGt(g90l9gD2EnSQ)Q~6c0+Qh#SF)xvm`4PoOY3u$HlzxdrjXB`Khyjv?Y0 zWZZl`1LQ_p7#}oK1RD3G(0rY#tPz_b-Z7*tmj)I1M{IJk}^uo^Q4KZZ20tQkW9Ll)Go5QaRkEXaf+ zxEW@uJr7DRgVO7u^foBH4@w_94jDtf0Htq1=_gS79hCk7 zrI}7Z)bpHx%+yOjX%#4K0Htl9vwgA@@BbMXzWrxl`1&7V3dls5DIgPJrhrU@nF2BqW(vqem?@x< z0}cj81`Y-$1`Y;h1`Y-m1`Y;R1`Y;x1`a3$u|Ogq8ITH)N{|jvef0l72gASr91MT| zb1?k*&%yBfKL^9F{~QcI|Nj7!5FSVrBnwgnQVr4tG67@~$V8CIARE{)>;;K{WI!rF zDnU9J8K%@QFzjh%V3;|Jf#LEJ28M6D85oj|GcdT{U|`^V#=xNQlYyavn~@<_gpom9 zi;=;|l#yYXCnH017$d{U3`T}G<%|qR`WP7=PGn?Qy`GVwZv!KP)EPzw`^$_BrEeJ- z0zNS^T;*h9_#no_uuFr9VZJ#N1GhI5gI)*|LrNACgJUTZLuL;XLnxxXr;wXioUH)8 zQ4+LJ#Wyp#C|@Bk2z+iGX#NyhF3GSlFo15%Mb=xES_GN^)K5*0&q*yy%~43s&rO0| zlbo5SfXgg(s9CTyCc?(R0GgK)3Q-NLiSv&B>3Ys#y8i;NBjulqR@Kg}&`*;{cFZZu z>=fH4{9NXOWD!Yun)3Bmd$9eGB9YeGB9YdGB9YfGBD_{GBD_} zGBD_Y8d9tbjz2&)o&+sK0c8jVCI$uu&|Himl0S@C85oR_>e`^xVuEcpkbaPXpgI@S z?^QN1Fi=iQOS7@B$jwoJ#=5PNp`L*f=(LQy6wuLBskTa$sl`h6b~eRj=?WFOIeEpl zN}x^nR{Hwo<>h+i#(Mch>H0FXr`>Eb0gq%?h$|B%4>6Z(THmNJ< zG$qjK$oh6RAW1t01_l$P_OvN01A`eW1A{p$s<;J|59@ryl4WYLg^{s7 zX1g{ivjo(t-EmQXAp*2(lL1n`!}y?G#GvvX#s{^nL443Icu@NnG`H*l+Cjs}!0>>9 zfnfva237_Jh8>Iy3<-=344~WLFMz~Ak^QfuVqrfx&@= zfgypJfgyp3f#CtjEEWca2h0o%2bdTb1VES#vd*ahs?UL)fnfuv@4~{spuo()FoA=C z;Q&<41!e{Y1uh1L59|yK3s@N#5p!tz@Wj$z@Wj!!0>{dfx$wAf#C)} zs13ltaD#(^p+k&;VTK?BLk156!wF6Xh8q$L3^Rlo7+&x)FsuOSkz!zYA;Q3*!Oy_J z!Nb6yAj`lI0J_>tfPrBH4+BGiJOe|41OvkXK?a5kybKHmN(>ASq!<_sgc%qb_!t;A zs4y^0kYQjrAi}^PAi%)zK%IfX0i;Ka0hB!%E@&|@7$`C@Ob};aSRll}@IaS=!9kgU z!9kLNVSz9M!wr1~1`kyR1`BBhh7}?V3_pw*7-pz5FjUAeFuV|DV6ZS_V0fX$z;Hs2 zfx$zZfnkOv14D%_1A~VG1H%ak1_lXR1_liS28J6-3=A1k3=BIQpk}BrFlfjyFjTlO zFuX8jV5m@IVBnBrU=Z+NU|3+mz+j-kz;FS?_hDeTV9me~pvA!OL4kq6Ab^3v!H$7p zf(`?NgAxNnK?noG21f>l4|)s?8#nSqm&c9?0hm71rP2n4_+3yC~{Nfr=RZ+&(;oGlJI>vn8_?>jdac`EC2Ye>I?;B+f zX8t(A;Zw-km8$6`BS z*_Ze!?DA?6t=M@jHkQHexsHqEb)9c)uU=AiMBMXDJx~6(oQ2jwnsY-}{Z44xxciJ< z)al6h4Rcm52;}}M_PVN6=eqy8t1q8DU;Cou+Lu==0wUJ4Lsx!-*0O=>7cNkp0^QXM zN>iZQfkC+xv;!1WY>F^2Fo4(~G0@yFhz6~N1c`y9!Z5ucF_0M`K1>{>7Q}{`2a|(|gXBQ^Kr~1U#74#-F_4+a zVjw;YgTz5>kU9_>gh6}|jVuOYBijMu!!S%Oh>xrn#0Sa2Fo+MrAU=qO;o-z*VsKou z4OE|i#);V&9QS}ZY@qwK7#z=lIHI899h59Vmk)!Ac~G&($l&+}B*_X&Ym5wzf5042 zB4%W8?AZ=75Hv!_$ly2!%mH;{7#SSbfH|P>V`OmL1LlAd2qS~z888QG+8rqyFflmp0dqi!fr-KK444CQ z8w-Qu9WV!UfF#HsFb8zv0uzJd9}q_sl=(oF9LQN9nwxqY4UNkf{*mkZBZ9 z^$HRPRkw*?+a1^JI?TXrss`pTFo4FwL7G7M7Ni(tF^CV+1mc4X1MxvOih-;JX)Xl~ zmVr7Qpkqrxk|6(q6obMQM1%YXqCr6mq9OidU;s7nLFz$)1QLft3ZxnMw3O|r5K)OMEkZzD_ zP!xk)0Kyu@*+qNDCj_ZkUkI}%IK{v*L#6fd!Aa{Y{8{|`vKR`hZ zVuQp%?gF_1}lP$CDJ1JVb|%=*y26)5yU@}STM=>>%z%p8!PK&OC#^np$t0I35- zJt+5pq8=0uApIb9ApIbDWc?tw6+*{*iomhJ0A4c=av#Vapl||(J4ips9FTb+H-pRv znFI0z$o(MoF!zJP55xzBA4n}I{6Ovog&)YBAT|ht^n&~eiZ_tCrBM4p`UDvq{~Q2i zB9NsZ%R!C@B^{6^kfT9jAbvhH$$=Wvus|1NaNKk7Fax(J$Yzir$Yzj6kZY6}9PfZ6 zkFtQm3uJE<0|NudU7+v=@j-iSKz;-12KgVP8^njX8DtWO4{|Ta37~c&NFOM?KzvaA zf#i|(gYA|ze~>zm|3U5m=?C#a`aya@`at%8!Vgr6g7kyJ6Qm!+2gN(ce;{)} zG)O-vt%3A|_#iVt=@n!Ss7wIq2l)@AALJg8zd`W^G6!To$loA&Q22rPAblV`Ap1cW z#0HrO(huT;^n=0?q#x#PP&k6jk%jKT0;NTeT97-C^@IEm(l5y1xaQbl2JWpaAXkHI z1?dLa0OlHo_Jc|QkbY2Tg6sv|I|GV+kbR)k4~k7tDgeoY^nv)G&;x}o$bL}G z1=0_47s!54>HwJo%HbgWAbUajLGmE|AU;Sxs3`%`4{|3+KPVhP`az)!(hph%0@4R^ z3oP}4)PnpAG6!THNI&SVPGtQcF_3H_Hp)vO>fPVWKik_nFG=XsyRS4=PDP`a%8%=?D1(q#txA4M-m-UdkC5 z7(o68=?A$3q#u;JLHa@A0MZYlLHa@Vf%Mx#OI%Rf>ollg0!qf9HW8Quat$Mc;~g*u z6y>0n510cgbwPU0fb@V20_g#BKt2Su*T5W*GZ`5i?}9k9`xqq|j~!?B{^`e7xMW#5 z*D{7S)(!mOPbW=%mnORY-G!gm{~VEt|JM2Z^;GU^mEX>Kwqbwzt-dZf0W4mqiDOF=D ztG7KhtjU=b8QHmM3w@ZQ_fKBA?a;#t?e24a+V88+U7IYCJWc)c;*RUD=EdzuEL-Kj zd&ZPMn^}_*W;!!x&NPV%7MwO;r(tI6pL<<*Rtwtr8`&DJ#ndcO6N0`s((|~U%IsV`={7ve7Sc`Pk3>xNeZ~#wjguq^VMmSq7Bm> z1rJW+lidCzZpniKjD8lA|30m3H@IB-yKerLl`{@JdU7kDq4Y&~!ei0rTj!{+lH#%E zpK{X7>FtH&Qsu0k zqq|*p`fam>pAsFcAJ^}d@qRUJia6(~MJ~U3B&KVwojBu${N`;&26?Ad{QBHn!rjj&@ZpuUs@L_(pMG6l=dm?z>7}IF z`8!s=*!f&2-*-}+lxU7{W?bRHu%5-WR`Z^|zm;y`R%E-qaXD|2U86C3Tz}yA`ctP4 z)lQP_S~Sx!v#R8sl*)~Q+9&*m9E;@Y@~uKoY)=wcBmeD{&5UA(~gr8fN_%HmE)Nr<8;djf$7O%5RrFO4- zl(C9^z4F$g2u=OPwQU|EFHDvBTb7%2@3=oT=9f^gVtwu*_RF7gox)azC+wbIw5IIB z_7g#y)zpHf{te8rx~&-*1ksyQd}eP?{9eY*$ z?tag*n_Klsnn#+LqGx<^3nPCdOF>io<=2m`lp|Wib(Wg#epnC}QSkS{sp8$qk*sEg zjXG8W?Kf6lR$*jGu=(hj@rvW;*Yb5Hl5-zupSmv`#P74@X^j7h+j$wHcf5p;A5Mwg zuYJ|SqHAI8?($!IJNNn2eUFuEVY9k=Vd;Yzt35(6Pq#Nzv=|HLI?_Xgzy%S)Vr7jo!s;wxqd5+TF9$x-@<9 zEjM5FW&4XxeciMDuJ;w`xAkXU+wFTHq_>(s>ATZnh7zN&T}F3)M;_1%tFIB>@pAfg zF+S^ws-I4`{fpceXYE*1nDX*GowEBD5g}EC~zYf-Ybn58}cFVV~Pt;`nTgo??!BR_p)77=<+oev1U%Fc;s^_R{ z^lrz`hiO(9Z{;qPir;a-qS4&oDSL9p|XgK+rW2SYg{4pQ-Ici6%mkWe% zdiOYS%6F-#C)?f})&Hq-)vR!<*TyrmZS}PnS|oKsbq-z1 zs>q(Zjwk&?ZefTExIbUblWm~e!P7Auuxay^2sGVf{ zw~9~uVn1g__UZ?g|9(Guare-N(uF~rzHL%83cLP(%a*O#JyJZJy`PUhI(l38a_a30 znXUC~Dc_mS94@)oIQ z9M(TvIZ4;?RAG|){U2r5;uxw_#hIR1RkCNc`+Y8R^SK}CVdR#7NbpMCR^_{;ueqO2 zom_oYqnPbPiqyAlx9YE}?8?iMb60T}KD;K+mTBdos1ECG&nKp-uX=vX`N(VJvX=bRB$t|+V14dhNU)JRTqA1`6g7{u|n5)JtzCT`Gzj#G1VK-?EZJc zuXk#>RK4kf*yC4ZB___fFzwbwmK)LfJ0|J(96nt8>79LYPS3MX@@Kd=eZD#8>hsQd z-#@6nyVj6=ORwu#L(J{m?q!lr&U{wyrfxiZch+iy03PdoPlU}c#1uSLwc*kaWH_L@ zdi~@E&t1Sb)$wZ`J2$!H$ERv~Tw8fGo?T~_ zZ~hyN%6|LsfWIH=Zu%;{$TC_H> zCpd3jY%=TR^o-vN>egR)==OLL%Z%=H$!yy*^M4(Dn7JTnIg_ctr{GIR(tm_q)?EF4 z{(Z#Dn;@Q3_eyCCwh$??Sa=O!C9Ydb$KdsxO~ zrVw;}{W0x#uccFW)HAbkEPj{i>B14h7F4OZz*XLzd|-d=5GAZufJ@g>cuNLoS{8^c-@~2LB5I22i(F z_XXrY9iJBh44?*f&I`yiQtt}^22cZd{R_y^0GD1swz_|N0XfuP`Xyv5l;catmZprC zkjrW(yc7T*zPa-yWNG~4mypAD`CdV`wOhS{Y~N3R1=*fH^%dlh-y^Rehn9bNCBOjc zK&ZYJU;qthg})X6A1vDST7Us`7}dVlknQ@PUkfmRrj9k=2!NOQCcJ?x)tK={fWeZ1 zf#KpC$Z-SQZv_}Y9VoZA0t_|`3=B5e5wg4F)3yIWS~k6k+6I z5Mk6{)L=AXlmkNsCJ_cMCJ_b=CJiPdCOI%0HKVisZ6VAfzZVutEv6=CIKwP8R& zIaUU^miwFxBiwFzUUKTkPITor<$(2+Vq=M$~K?lHm5@3jAU|?7T zJw&ww%AXJALk~@I&PXguOfE?+g7RIHGhI?4ClllsAuSt&s|!vofhrAyEF^PDEJ+N> z&-cmCOSeN>;%?8%z~I2jz~Bg4f~_#{+k}>XM%^al1nLArhx|axr5y9}^D1-mON&7# zyk)0W%6@^A51^ac^dX11fp0wnUqk>>Q=VT0+6trd1(GjeLLpxu&F$ zMA${HwrVMv>6sI=J$_f(fVD~}20WuIA>?CMKkFlWA zGSI!rdBtF-lsIQ3=B20RrpsOn30RTGeskA5+8rZ=Fc`l^|;G1YuAwdH73seQ1A5vM63OOIy zKMg7ul$w^ASK^mn5?YXvnv)V*nwbLPfP)sq0Xqts@LcmsiYh^ZP(JurVbIB2sYQ_c z7N8D;gf2)S+$fZ^>;_7c;Dis30rX&mXa`H7M-KErFL0d0N*FijRqsxTDL$ZpPYKD- z56;LhDnYT+9h`r1bMx~+r%M+*=A{Ief-h7ob}UMDO)Rbq$#*YJEe0QHjV$X_8IqBj zTb!CxmWrm*C9wo72TY@4)D**sSF0+VwF?rkywwWW!QbS6M@`?kB zQd2UM!FOE+mnIdLWR{eIE~6@T$uu(mt@w}XL{I42flmVh>2fv>-F$xkgtwb3yp z#W61*bhSFjZ~jFg<@tX3eyOP`Zuv#QmAOgzImIsE+RVQQZmmyhNl9uE*z0bo#q}IH0;J8I(vt*UA?cL$2}-PAy7Fbxz7J0tXhD=T)2!sr=lE zA%fr{9?XOm|E_uInR&269(u4L*jlJFAjKrIh+}dAG8YuokUGc{c26~^OonO)#|^S_ zWH#so+SK9_WFfG6xItlwIi;z{($1i*rN{y`crqjRdDwxN(Kw$v1`@BH$8 zL0h{s^U~qYEk=lelw_tB!(s>21cL<=B#pRM6o5|c1t0HOT##2 z4I8i|>zkGc^*W+R2OTpGlMl!*&a8l@fntbl@sRsZ!RJ$^f^4n??TE}ttOS`0x<@V^ zdM#agQGRJbacO3JMrK|~@w)$z{``*rkpBI_|ByCw*ndd-x(rGm{|{-u2LFeQ8(jJi z>G$7*s(!5jZ{v&1{O6{d{dJ%K=-A?1sp+Fg@PPdnyUa(0L~pyBS3uE74g9tiKd1|!5N80 zre?tziH2YUKu2IZ=A`F?Xh=I5dRj6lvLW3RG=Btx`k6WD`N;7Tg76!{AgB|ZL!l)d zI3iH~7lZUd3lWe5LEMm{O7NBHAhvTxYH~J89EPznF!<%?L7VEK zL8<9r&nGA5#V63`1oQ5So(vd$8sh?2G9&+Bau6G7CNI?6D;!BG_RcAqJ9%#>S zer8H?d}>7r^tg?9P&hAV76czTxrJGf0W`V0mst?J6y*@JAOmPJ{v4FP1r@&!rJpcE z!u$|IQ-F09v+z?Dj-7wvYBIQ;tDjU-l$xramske6JTXmpLMB>q`OUi$u^~fcT`;_{4b7`AEq~+j>%2 z85m%Xg z;H!huiW1X7Lm?CnHkKCU=o;x6>luOrBquXTuc-Jdn;=6ls2t{k?0kgrt)YAkO$LTc zq;esPm4P9fm4P7#91b}-pyMb8L;S60hr}Nj69WTiVM#8Mn?d;-nV-kXz<|upN8=Zu z@e9%TMQHqDG=2%F&6l5>T8iX`GH88*ELILmD@bZ8(D;>T{3C17(n8nG6IC#Dc?p2I+#Y+K+j0e z$Q)cSq$HL=%0wP+i2si;K@Qx{&Ce^zNJ*^3?rV7lY<`w!kYSK#kb`1mmMl~ZB!>{E zFfP&k0=j+(T)y9c`USKw4K!^Kl9`*DkzZQWffUA_pnRN}S6Y$^iJ-j1ynG0YfdN@v z7bp*aBN7x-Ad^ZY6w))x zQu7qR$EX#9_OF45S`-QrixP8FL4zm^3?{sS;JL@df&$R_?x`tGIr&MTsgHo7{DR`5 zY*61PEVU>zEi)P3&I9!z(ZwNkLShbR;0e(w@pJ(Vcj8iuPzN2?$jr|R$j`}41|3aZ zgw0k^O^Ym!&sJP&VT~3ieVB`JWmGq`O@-> zK*x!}J9U_vko8Of)uC{;P#fWXPR#?G267C<1?URUTlOH8px6pdEnz@$+f=AMFxP-Q z6`z!opHy0w3uYI9;x;!kFTNl%FCNqxD9OmkO-znYE=o--NsWhgaTyHwA#H3Men{Kf zl^>F>Joq8)&LDnByEB1b5WJlW*{{=BQQb71m4N};5DZEMoyr9nLUDy1ZeN_6nHP|m z=aZV34snb#*e#HbB(%ASS3d))eKQdDfm)}a5QQXQgpKK`C9ohwwE&j}kZN$Y!0rR* zoXpg`693YYg3^*=h(=50393)Iu8r9?=?}OxTFYl{%m4i z3T!WI68Ky<$dw}?wWKrw7-k{m9ne~c*+_g)pO`{VmqUkRb&HC1K^Zq6>}N>*1{$XY z*9i{X0mrGXrVSt4zxcBv_lA~o6G={18rjgty2JXGRi@T0hFo| zbBbZ|puRF_@75foIrX`$3=H#F85rh+#ySSUoceDeK?ZLI28Lan4B$Q^Xp22)KOAVm zJ7`WFFo8fNta?q;Lckr0D|QgbRZ^U?zni%P&_rVI?rko>Wnm4N{?xKac< zP#IY%$S?*}wV*lyIvx=Z8jypsK||fp!Vjb=pft%lwGx!H13+zrV({o=Voo}$St~$o z6wtDj60ptanp`qLLpz>%DPS5@uz^mO1PzsC=I1%*=ar>aCgvrlLc%gNFF6&WFcYdF z4>k%%Ko@AL8Fbl?Q%m09UldZ5m{$zyWP=hCNLf-&YF=7$X>k%bxUs7Z zfE5U!5P)QEm(=3qqRfJl{Gt+=iN(lquo5vIhF7;U=z61ooWzo}{GwbKjp7Q&l9I&a z3{bZpd=-*z0aP)J#&kDA2Z}+#sX35=59cD#O=y{kpaKx&o8-ij{G#|oxIM`JSjEb~ z08OItMXAN$#t~=$4p|MTP6f59;>(a4glOq(HK?2`Ey;k}hj1j+_#mk1-l-VPJZMV9 z?;A(ZAT=U_V56ew!k}>+Xq`(;A9XEKz5>-x>yY@M`U#X1C@c$!s-s#YAaxYzs0C14 zJ~M@Z0VW2jTR>unl!%Z6ZO!xtUAhO=54wokje&uoD6!lVR4>8ISkAxzF8^TzwJ`CO z3=H6-Cs5J~Xq_06nQIsz$8kW`nw1uT#>!y&H!?7QkDvji50AvWl$=zA+d#)UdV=Bu z+&}^u>J{wohmhY3wcA7j(vN}E%evXAmGD{^)FsLm>%i4q$IVtM6amWM_Lek>@=uO2c=n1I);gX zHbH|n&>^Q|m>eigfyO6cd{CRq3n?AL#6d?Df!Z;!bPN;U1Wikzbsf+u2QpXAz`y`g zvjv)tA@dW6^azvR2{q%76nc6rDgY%Rc&aQYO#+pXpng+IJh)d~3{9v=)~7;NzkwBj zO2x#SVw6l4Ukod+5viMjp-n~*yi31BMi6}LWseM`4>naskO8!*ZiNhFPGG$ZWKL-p zRQ#-rAb5@P6B$S!Z6i{8*u=`ffXv^F#s{?#kma|a$!|sDZ$sm6N8|56mY=sBct0F|NVk@%o8 zR3Fq-CjS^WyzKy3`PriYDL?HQ7{F`qA!!rRSB1%eF11DPtHR_!{ZtSJl~*t^&)Ivdoc0F4=e2AW{vpmG<~KEceH3=A+eprZ~zZ4%JnfjW5L zvM3dLUtVeo_||v@uf(#%U~uDFA+IzyDYa;aBBZ9q< z1}h~&22i*xWn=&!)e1WeA9fYO1<-&qbe%frxN>BEAPdDuv*R7$fz0wTFq~0>v?EQS z$67lmL&EkVlG`q^GB8|5O50ah85pjzGB8|YWnj30G=_1Lm4V?FD+9xAP}_bGjA86o zMjgYrgXAaB7zXSpI8d7%?e-7`9Tmu!rIiY#-UP2^16{9#6b^S;85r(C&HN7q6y|x* zLMzaX6M9DAVYt+yqWmIAVq$12i5DKP4Q`onV@;rl6=reJ?J(C@J-7M3~y8f z89;3*(D7`bQ4@vCyn@ma1_mBgh@To%AoDjf85qF(i(ugZUR|XC8RrGfA3*q43h-N1 zbQIF^OY>4ddy-641;Kljf>a^l6RQeYM}cZqa(-!E36cS(a1$C-1;NMpz|=!*MN(>L zrjS%wl3EPc!N9OVRS>+738x;2AqvJu;Cm8^!57znn7N51Fk_ym3WE0>!OTd8ZIVH< zIx$ZnAAD(aVvYi6Tqd&uG$)c!T9gOAX5A`5AuS)&xdh!5P^l1Yplg|^Tji)56$`T@ zAweOrM1es=O^_jufq|h-4YC#`5gb3z5mN>RhB<1Gbr@iOGB7Y~fvSThC88S^dBos7ESg_&1g$ExPMjHQ!x*!AS zh^G4t3=E*LQyBjN8vh|0{}GgrJ|Br)zaSXQDiFw|>8)}kEegp`3W zz6o?K3XBh1n*yJdfHx%|GZYG;K|Zj_2!C(}$2-3QQ%X!zkl``39)OLHCl(i{7J)_p z6d%rBg7B*~3G0lKl7iy$;^MTDg0#$>RI0`=B4;u%#A`$9BoRgi2GHR$ zF#Z-s2JoI!eSMJiR{EfEdzhRa69WTi>NYYnFo4=ap#60|I)V(KIEBd_V`czfnGNF~U}j(d9c}~T ze`97~03E&qZU%xDbTJ_OCdD`;&E#K*mmK}OJ|R0GHbyl8yT zAOc8|k%6HBrXO@^0_ae5swQJ-Q(8k0QcA%}AsF8YT1tfm`4lVUg6Z9czwRp$)DOzbFVRg()lJj|&5D5vErk@&j+jRcGfNbp2MvQ#7U)8&;?$C& zRM13MSt?i|C>#~A7y>d0Lm?=@6BR&GnR#WPO_K^K;MHCV@J10#+%ureOd&BPr3kcM zAF9?fpv(ka3^b7f?WDo9Lg!ULMPXtN%mUEN66D}ukVhC8o*?zmpRzJAJY!{Gc#b6Y zf|Y^c6;e;*H7f(d8&(E}w}Ygop=|&uabdHi&{R##EIz|Kw3>t5ngDTFbV-pu^a=}5 zZE(Z@(hCJ$rU^O-lB#JR6n%O{#VUq^44`AVgP^NqVf-d2ACx~C9G5>n!oaI!I zQ|r&j0A9NUHPBk^s&&f$5vNo z7(r6bLpI3zVq)v+;*!Lo5={mMnEpr5`kGk%sd*`yFujkVda0fA9E>3;Z#yI8N=ahf zMvFGl1!G7!!`ejD_N$Hws$VJ0Wtk~?iMj@Qu*DFiCB-IYpv=tBV*+U>f!aBs!}4H! z(E2{mVTUk2XiN{Zw*a#Xf!Y|tYu&T_wqqAH#!Xr44|1BklmnO zN^}DQ!*>P-hL{Ehh93+J46z_X85zL6Y$HYnh6xP}3?_^W3=t{gFh1kLvJJGLJg3ccQP?BOmAdhIK;%j zFr$%y;TRJG!^}nohD%Hg46_;;7;Z2zFwACTV7SM`z_759f#CrY1H&Rl28O3h3=GQ~ z85rI$F)*wExrd2?VRa(|_@<&YjSLK+OB2>IGBCI?Gcas!WMJ@TW?QP|C!>aE^t6VP_NM;*ecT3=E*1QjX0G44@rR zPR)=VJI>7v44~aNF3k)Kpq0_C%nS^mRlV-bkX5xF%?u2nmA9VF3=9)k85q2p85lrq zP48v~2G9(L56DlT)xFIO44@f`fMx~;(9A?&GXn!?#vzCqGRqLs%)kH|#SLv{U;wpI z!kR%lNEjHxn;96svNAA4G&3-;u`w`2HZw2?urV-1H8U_svoSD4H#0DR+NLqh3=DE? z3=FZ&3=9fv3=DD23=9rz3=Hwj3=EEJ3=9d)3=COp3=E0Q3=DZ}3=B!l3=E}g3=GN4 z3=EZQ3=HYb3=CI57nw9OFkEG0V90D{V7SZ1z>vkvz;K_9fgz`vf#D?^14C{z1H&se z28O(5$Vtrk%?u2D>^T@1YC-v+sz|h>x zz_5UWfuW_Dfnh5L14C;w1H(2B28Om~28I(H3=Hkf3=Ee+7qc`oFg)U5VCZaSV0g^I zz|hsqz!1U7z|ajckCTC6ax()%3MT`@lx7BoG)@MFsm%-w1)K~F)0!C=3ON}VrZ+P% zv~V&o%xGp{Xys&Jm4Cgr+7*;hiFkI(kU|8MEz;J_;fniNE1H&Co z28OlF3=9uA85lM;GcY{iWMJ6T%)s!BlYwD#GXujXP6mc8%?u2GI2jnWGBYsz=VV~m z(agZW$i=|0vzdW`g^Ph;1i2U(_BAsw z2y-zo>~CgZ(BxuZIMB?%pvA?&aIl$y!H|oA;Se(eg9R4@!^vg_1}iQGhEvT93^rU0 z45yhH80@$h7|u2`FgSBDFq~^1H+wW28J>&28O%M3=HL53=H?0 z85kP57#Qw@;){!c;Q=VVxEL57HZw5vaWODF0>u{>1HF-htwci-F;NGXujZ(B(s*c;jMV_}I+AaE^K$!vzdY6Cl>?5FHpYWW?=XYiZ^Zs zhCiTq<7Qy^3yL>x28Msl3=F*73=IE4@x~2Wa>KwN$j!jO*uuad%+0{S)WX1^$<4sP z+`_=1#m&IL(!#)C$j!jO+QPtK#Ld9K*22JG!p*?I-on6O%FV#Q(ZaxB#m&IL*}}kJ z!_C0J)xyBw%FV#Q-NL}&&dtEU)55^u$<4sP+rq%$&CS5T*TTTy$IZaN-@?EU3c75m zg@GZ0n}I>Fg@GZ4n}I=yg@GZSn}I>Jg@GZ3n}I>Bg@GZBn}I>Rg@K`fn}I=sg@K`n zn}I>91#+p9bPEGR6E_2cObY`;3pWFUYzqTJD>nm!Tnht3H#Y-=d1A}D?1H&_J1_rAZ28IvZ3=GyS3=F@y85nF@ z7{Irj+qN(;@bWM)*tIY)@bNG(*tak+2=Xv6IJ7V@2=Op5ID+Dnhk?Nf6rVf{49=kV z;$dKLX<=ZnwlFY6^Dr>@wJcfgu1CZ#)bPfuMNfVPFVq zVPGidVPFVuVPI(BVPFUW#TO3)LntV|co-PMS{N95c^DYNLGi`Izz_k7FCGSlNKkz7 zFfc^5Ffgp-VPJ@EVPIIr!@v;J!oaYFhk+rsg@Iu!4+BFSDExUC7~)$P820cmFeJ1v zFdXG!U`PaoKMw;#5-9w67#Na4;m^askOB&S9tMWg76yi^JPZtJpm675U`TIaV7SM_ zz>opDSd52(A*+Rf;Rz1|LpCTLco-ORK=HuCz>wR*!0?fWfg!Jjf#EX`14BM2K0ud+ zf#QRgfuRr-AG{0Z$Xmw}co`U`gTjxO zfni1q1H&g?28Nj}3=Cg*85m}@Ffe@OWnh@y!oa}D$G|YBg@M7CkAYz>sJ!80V3^m! zz+lbCz%ajsfx(`Sfnh-l1A_w}1H(d4c=0hXECPiW9|ObU76yhWJ_d#*pz?%|fnh1g z|9lJ#%UT#1n)w(Qma{N0wDB=8tOAt}d<+b$TNoI6_!t=0v@kF%;bUM}%fi60oR5KF z11KE$7#KE!(itBE!zNI^=3`*k31`KLf+D76t|deg=l)pnS~Fz;FUo{_-<0oMd5O zu;OQ6IM>3!V8_qEaK43s!I__d;X(@og9|?c!^IW`1`mD)hD)Gy#?QcTxrKqjm!E;* z3MgOmGca6jVPFX2XJEM2!oU#B&%kgUl)w2I7;b>l8$ScXO;9-UGceq0VPJ^mXJEM9 z!oZNp&%kh}g@GZ9pMl|S3j;$gKLf+P76yhweg=m7Ees6B{0s~aSQr?p_!$_UgTkMm zf#C(HoaSd>c-g|h(8|xi@T!G@p^cw`;dKiG!(@I2hBqw?3{&_S7~ZxpFwEd*V0Z^A zm-!hO-nTF?%;jfb_|U?@Fpr;s;bRK}!y`0V*H(85n-HFfi=pXJGgRicfw9hTov_fuDil z4=7#pGcf#ZVPH7R&%p2x6rcPI4F6jg7;b~ki*JS8G{xA;z~Cjoz`)eXzz`t7z`)$f zz%WmMfq|u!fnk9F0|RR-1H*9v1_riP28I&?3=Hh83=C%l7#KKO85qt9FfeeoGJr4Q z<7#DK_$|P|z|G3Q@K=C=ffr=HAOizmD+5EkAOiz`D+5EKAOnK{NL+}4L9ms9!BdEV zK?r2O5Cem7D+7a{5Cek<$Q?oq45FkD$c;*-^#$CAkM%L(8|DID$c+V z*vi0QF3!LZ)XKo%AkM%L+{(ZZBF?}N0`jjo14Agtec}uZVXX`ddEyKV;jIh|h2jhh z5v>diMdAz$k*y32CE^SWQ6P7VGcZKAGB9irXJCi{#g8}xLu@Mp!xeD`hB#38i!(69 zgTh~&fgz!lf#Hrg14Cjf1H(OW28N_o28IXX3=GMw3=FTt85mMp85ll@GccsKGBErS zXJAMJ`AdRflY#eA)}Rnfn9=uA+wc%fm?!sAq(VB2?mDjRt5$E2?mCoRt5$s z2?mB-kbfl@81h;f7%C+g81g~xlwe>eXk}nnEy2K0*vi1LL4tvy2ozru3=G8}dn6ec zN?I8hwzP}R!7;3&z! zP~FPF;3CPuP}9o5;3mnyPzwq-Nd|_xRtAOwNd|`cRtAPrNd|@nkUJz97#dp{7}iKK zFf@VOA<4kd+{(akN|J%01(XjZ85mky85nL!GBC8YGBDhhWMF6qg_k4)LkGy6QVa~8 ztqcq@QVa}TtqcruQVa~;Aoof!F!X@(sT2c4FDM?R7#R9M=~jw?p}&=Zp-Iu7`B4^EyKV7TDiMhhJoQ>D+9w`83u+&tPBhXWEdEp zg31jU28L&#c#vUWc;3pua2a&TC@4M4FfhCXm5(wE46i`$lVxCd4N4!fkU5)dSq28} zHU@?YSq283HU@@DSq28(HU@^-vJ4D*YzzzsWEmKO+ZY&r$ucm6v@tOJmStcFZDU{n zEjJ2dV_=vn$H4Hqje%j790S7}HU@?{atsXb+87w-$uTgzXJcUaFUPPAw!;lp`D$9p-!HGVQxDELxVg6!#s8dh7Ixz4CmSz7&gf> zFq~&+V7MU9!0@)6f#I?|1H-#^28Jv03=Hqv85pj~GcbH;XJEJ?&%p4Joq^$jJOjhe zb_RyW@(c{W+8G$0$TKkfZf9V4AF;>3?&K- z43-=W409D27?L^|7#1inFeG;{Fsx8uU`Xj;U|6ZZz>wO(z;Hl;fg!Dff#HGz14DWT z1H(rJ28N6d2Jn)AOb!MHZbb%$k`4w2enkd`Qc!p(GBA{NFfa%yGBA{PFffQHGB8wd zFffQKGB8wkFfd3eGBDI|Ffd3fGBDJ2Ffhm|GBDJ4Ffb@6GB7l7FfiyVGBEUaFfbT` zF6iZ8V6atWV3^avz+kV)z%ZACfx%Icfnk0J1B0s~1H%GPxF|9(EChv%A_K#c4h9B4 zMFxhYpfNB-28Qb$3=GYRkV}VK6&V||gl(PCi8;$&bb*J5DE?POrM zqs73G*U7+eSBrrmA0)5Mz);Z1z)+^mz);x9z%WglfuX3AfnmBf14D5q1Nhdo5>5sN z104p2C7lcm@j46)OF0=BQgs*@R(CQmr0Xy+tl?x}DAr+M*wM+rP^!bguoGmS4gOq>M$@UcQG)$)?r{!0gd74FfgchF))16fn4mz~I`&z;Iocfx)ed zf#HTO1A}`P1H*mL13-fPulTn}K1b0Rw}5 zHv_|L0|o{MZU%hk5fgxl}Yl0yI!^&<3hDnAD46C>q7#0{ZFzo1NU^rmNz_7EMf#HcE1H-Ov28IuY z3=F$L<`^+B?BQl$@GxRvVCi9C2ryz`Ue6fG-2Xwq6DX20sRd?Y#^P zf9EqW>;Ul>Ffi=wWnk!C!oaYrmw{oz5(b9dy$lS;moPBw>1ANJu!MnOZ!ZJGzaO6$$6f}8l4T4GpL!V>>XtDueCB0fn7539LAZ~B;n^|<29Z7nh7Zda7)1LR7(Ojy zU=ZtLVED0&fkC{Ffq`K;1A{~#1B3W-1_sGK1_p)Y3=C3z3=B%k85pGb7#Q@IGcaiM zF)$b{XJF9eV_+y;&cKk-$G}jzoPi;ekAb0mIRis^9|J?@at4NqJ_d&F*cJMJU{94Yyu&a-OL1P62!|px?2AvfQ414+* z7<5-KFzoGPU@%z0z_726fx&781H=A41_p-}3=9YQ7#K=cFfbhKV_>LQ!N72+kAb0K z1p~w3J_d$kD;OA#^f54;Tfx9^w2y(|!U_h4V|@$^w^lGP9PeXbc(8(j;RMM36$}g~ z`xqF0uV7#}#mB(#cLf8(nLY*vy_F0MXF>L^WMDYg$G{M>l7ZoT9|J@DN(P1teGCk> zD;XFrg6vz#z;LOLf#Kjv28PQZ`&KeATv9B2J=-647Wl4TE)O{r;mZbZxsW>-983}fK?0(_xczZ zqE<05-0x#xh*`zJ@Su-@Az>8*!^1uXhVoSm43GL47^+q=Fg)&KU^u*rf#FFX1Hr1B2jd28Q>bbhMg*;R7fgt!7~O*vG)2zM6sI6DZzR zGcbJaV_?u<&A{*l6mF{-7{2x~Fhs9rVED$zz>u(-f#G)_14HI&28KU<3=CPT85sWd zF)-w;W?=Z&$G}jqnt|azDBY}PVDRr}V0gWnfgzxuf#J<+28O_X28MU585n~485lmS zW?%^JXJGiXnt>stpMim44Ff}HKLf*(>kJHG{R|8nt}`%%_cJgYzs|rA(a*qe`Z@zc zWIqGLpX&?^Q6Tj{85pAZ85r1qGB70dGca)eWMD|Y zF9wF32@DLPzZe*D1sE8Ve=#srPhenB{l&mgBf!9*{)>U3ZUO^?)-MKzdI1K8*k23` znoZZ&=X`}VExU&U_6n5 zf&DiFgULh&2I1cf45oq%3=+Q?7_25TFv$L9V6YZsUqhQfg$KO14I5q28OWT z3=9Pm85p8|GcXiRWMGK<&A?DJk%1xUHv>cQL7TO>qG{I1-}^>+9onEEcwmA&_0oYVcBm6hK`9046A-K zFmz62U|9E?fuU<61H*>j3=G{985lPGW?<-<$iQ&uHv>cOL8-uz}@m^qPw;oWZrhFKFC7(V=FV3<9T zf#K6{28KBk85q9&W?+~*k%8gcZw7{W6B!tO{$^m9Kaqjq&u<2X1)zBR!@#gmkb%MG zF9XBfNem2je;F9=O=4hh_{+d>e-Z;jz+VQ22a^~W0{=2FJec;gJvnL&RSO zhUb$Q7^40%FuV|AV2Jhw14H6p28MT&7#NcNGBCWK#K4g9mx1BKBnF1GzYGi? zCowRj|7BqKG>L&B^DhI#=Sd6F`0p({VxLp=VS(k&c6%{T*3?t6aF$V2u@~TnDiGiW;FdT1B3Wv z28Nk`A!9~!{xUE~PiA14_m_b|Mwo% symx5*3)AO12hxC=8d{QJwm5IUKGf#Dwm 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

8{(2J+u8Mh5e_3=HkR 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�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 for AdminListAccountsMsg { fn from(ge: GetError) -> Self { @@ -476,6 +478,7 @@ pub enum AdminViewServiceAccountMsg { impl Component for AdminViewServiceAccount { type Message = AdminViewServiceAccountMsg; type Properties = AdminViewAccountProps; + fn create(ctx: &Context) -> Self { let token = match models::get_bearer_token() { Some(value) => value, diff --git a/kanidmd_web_ui/src/components/admin_groups.rs b/kanidmd_web_ui/src/components/admin_groups.rs index 5949d8b67..951ea055b 100644 --- a/kanidmd_web_ui/src/components/admin_groups.rs +++ b/kanidmd_web_ui/src/components/admin_groups.rs @@ -1,14 +1,15 @@ +use std::collections::BTreeMap; + +use gloo::console; +use yew::{html, Component, Context, Html, Properties}; +use yew_router::prelude::Link; + use crate::components::adminmenu::{Entity, EntityType, GetError}; use crate::components::alpha_warning_banner; -use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE}; -use crate::constants::{CSS_CELL, CSS_TABLE}; +use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE, CSS_CELL, CSS_TABLE}; use crate::models; use crate::utils::{do_alert_error, do_page_header, init_request}; use crate::views::AdminRoute; -use gloo::console; -use std::collections::BTreeMap; -use yew::{html, Component, Context, Html, Properties}; -use yew_router::prelude::Link; impl From for AdminListGroupsMsg { fn from(ge: GetError) -> Self { @@ -282,7 +283,6 @@ pub struct AdminViewGroup { impl Component for AdminViewGroup { type Message = AdminViewGroupMsg; - type Properties = AdminViewGroupProps; fn create(ctx: &Context) -> Self { diff --git a/kanidmd_web_ui/src/components/admin_oauth2.rs b/kanidmd_web_ui/src/components/admin_oauth2.rs index fb13f1aaa..c57a90525 100644 --- a/kanidmd_web_ui/src/components/admin_oauth2.rs +++ b/kanidmd_web_ui/src/components/admin_oauth2.rs @@ -1,14 +1,15 @@ +use std::collections::BTreeMap; + +use gloo::console; +use yew::{html, Component, Context, Html, Properties}; +use yew_router::prelude::Link; + use crate::components::adminmenu::{Entity, EntityType, GetError}; use crate::components::alpha_warning_banner; -use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE}; -use crate::constants::{CSS_CELL, CSS_TABLE}; +use crate::constants::{CSS_BREADCRUMB_ITEM, CSS_BREADCRUMB_ITEM_ACTIVE, CSS_CELL, CSS_TABLE}; use crate::models; use crate::utils::{do_alert_error, do_page_header, init_request}; use crate::views::AdminRoute; -use gloo::console; -use std::collections::BTreeMap; -use yew::{html, Component, Context, Html, Properties}; -use yew_router::prelude::Link; impl From for AdminListOAuth2Msg { fn from(ge: GetError) -> Self { diff --git a/kanidmd_web_ui/src/components/adminmenu.rs b/kanidmd_web_ui/src/components/adminmenu.rs index 61f84bbf6..aee95b581 100644 --- a/kanidmd_web_ui/src/components/adminmenu.rs +++ b/kanidmd_web_ui/src/components/adminmenu.rs @@ -1,13 +1,12 @@ +use serde::{Deserialize, Serialize}; +use yew::{html, Component, Context, Html, Properties}; +use yew_router::prelude::Link; + use crate::components::alpha_warning_banner; use crate::constants::{CSS_LINK_DARK_STRETCHED, CSS_PAGE_HEADER}; // use crate::error::FetchError; use crate::views::AdminRoute; -use serde::{Deserialize, Serialize}; - -use yew::{html, Component, Context, Html, Properties}; -use yew_router::prelude::Link; - const CSS_CARD: &str = "card text-center"; const CSS_CARD_BODY: &str = "card-body text-center"; diff --git a/kanidmd_web_ui/src/components/change_unix_password.rs b/kanidmd_web_ui/src/components/change_unix_password.rs index 61a00de26..2ac1bea12 100644 --- a/kanidmd_web_ui/src/components/change_unix_password.rs +++ b/kanidmd_web_ui/src/components/change_unix_password.rs @@ -1,11 +1,10 @@ +use std::str::FromStr; + use compact_jwt::{Jws, JwsUnverified}; use kanidm_proto::v1::{SingleStringRequest, UserAuthToken}; -use std::str::FromStr; use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; -use web_sys::{FormData, HtmlFormElement}; - -use web_sys::{Request, RequestInit, RequestMode, Response}; +use web_sys::{FormData, HtmlFormElement, Request, RequestInit, RequestMode, Response}; use yew::prelude::*; use crate::error::*; @@ -85,6 +84,7 @@ impl Component for ChangeUnixPassword { pw_check_val: "".to_string(), } } + fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { match msg { Msg::Submit(data) => { @@ -303,6 +303,7 @@ impl ChangeUnixPassword { Ok(Msg::Error { emsg, kopid }) } } + fn reset(&mut self) { self.pw_val = "".to_string(); self.pw_check_val = "".to_string(); diff --git a/kanidmd_web_ui/src/credential/delete.rs b/kanidmd_web_ui/src/credential/delete.rs index caaf0142f..fc5d07fd5 100644 --- a/kanidmd_web_ui/src/credential/delete.rs +++ b/kanidmd_web_ui/src/credential/delete.rs @@ -1,19 +1,16 @@ -use crate::error::*; -use crate::utils; - -use super::eventbus::{EventBus, EventBusMsg}; -use super::reset::ModalProps; - #[cfg(debug)] use gloo::console; -use yew::prelude::*; -use yew_agent::Dispatched; - +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 yew::prelude::*; +use yew_agent::Dispatched; -use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus}; +use super::eventbus::{EventBus, EventBusMsg}; +use super::reset::ModalProps; +use crate::error::*; +use crate::utils; enum State { Init, diff --git a/kanidmd_web_ui/src/credential/eventbus.rs b/kanidmd_web_ui/src/credential/eventbus.rs index 1f07c85b2..ac40c14ba 100644 --- a/kanidmd_web_ui/src/credential/eventbus.rs +++ b/kanidmd_web_ui/src/credential/eventbus.rs @@ -1,9 +1,8 @@ -use serde::{Deserialize, Serialize}; use std::collections::HashSet; -use yew_agent::{Agent, AgentLink, Context, HandlerId}; - use kanidm_proto::v1::CUStatus; +use serde::{Deserialize, Serialize}; +use yew_agent::{Agent, AgentLink, Context, HandlerId}; #[derive(Serialize, Deserialize, Debug, Clone)] #[allow(clippy::large_enum_variant)] @@ -18,10 +17,10 @@ pub struct EventBus { } impl Agent for EventBus { - type Reach = Context; - type Message = (); type Input = EventBusMsg; + type Message = (); type Output = EventBusMsg; + type Reach = Context; fn create(link: AgentLink) -> Self { Self { diff --git a/kanidmd_web_ui/src/credential/passkey.rs b/kanidmd_web_ui/src/credential/passkey.rs index d8cca8066..f87908c31 100644 --- a/kanidmd_web_ui/src/credential/passkey.rs +++ b/kanidmd_web_ui/src/credential/passkey.rs @@ -1,19 +1,16 @@ -use crate::error::*; -use crate::utils; - -use super::eventbus::{EventBus, EventBusMsg}; -use super::reset::ModalProps; - use gloo::console; -use yew::prelude::*; -use yew_agent::Dispatched; - +use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus}; +use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential}; use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; +use yew::prelude::*; +use yew_agent::Dispatched; -use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus}; -use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential}; +use super::eventbus::{EventBus, EventBusMsg}; +use super::reset::ModalProps; +use crate::error::*; +use crate::utils; pub struct PasskeyModalApp { state: State, diff --git a/kanidmd_web_ui/src/credential/passkeyremove.rs b/kanidmd_web_ui/src/credential/passkeyremove.rs index 4aab0b9be..292e418b6 100644 --- a/kanidmd_web_ui/src/credential/passkeyremove.rs +++ b/kanidmd_web_ui/src/credential/passkeyremove.rs @@ -1,21 +1,17 @@ -use crate::error::*; -use crate::utils; - -use super::eventbus::{EventBus, EventBusMsg}; -use super::reset::PasskeyRemoveModalProps; - #[cfg(debug)] use gloo::console; -use yew::prelude::*; -use yew_agent::Dispatched; - +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 yew::prelude::*; +use yew_agent::Dispatched; -use uuid::Uuid; - -use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus}; +use super::eventbus::{EventBus, EventBusMsg}; +use super::reset::PasskeyRemoveModalProps; +use crate::error::*; +use crate::utils; pub struct PasskeyRemoveModalApp { state: State, diff --git a/kanidmd_web_ui/src/credential/pwmodal.rs b/kanidmd_web_ui/src/credential/pwmodal.rs index 9e42be8de..5aaa808b7 100644 --- a/kanidmd_web_ui/src/credential/pwmodal.rs +++ b/kanidmd_web_ui/src/credential/pwmodal.rs @@ -1,18 +1,15 @@ -use crate::error::*; -use crate::utils; - -use super::eventbus::{EventBus, EventBusMsg}; -use super::reset::ModalProps; - use gloo::console; -use yew::prelude::*; -use yew_agent::Dispatched; - +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 yew::prelude::*; +use yew_agent::Dispatched; -use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback}; +use super::eventbus::{EventBus, EventBusMsg}; +use super::reset::ModalProps; +use crate::error::*; +use crate::utils; enum PwState { Init, diff --git a/kanidmd_web_ui/src/credential/reset.rs b/kanidmd_web_ui/src/credential/reset.rs index c1f1b1c15..28f1cacde 100644 --- a/kanidmd_web_ui/src/credential/reset.rs +++ b/kanidmd_web_ui/src/credential/reset.rs @@ -1,19 +1,14 @@ -use crate::error::*; -use crate::models; -use crate::utils; - use gloo::console; -use yew::prelude::*; -use yew_agent::{Bridge, Bridged}; -use yew_router::prelude::*; - 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 yew::prelude::*; +use yew_agent::{Bridge, Bridged}; +use yew_router::prelude::*; use super::delete::DeleteApp; use super::eventbus::{EventBus, EventBusMsg}; @@ -21,8 +16,8 @@ use super::passkey::PasskeyModalApp; use super::passkeyremove::PasskeyRemoveModalApp; use super::pwmodal::PwModalApp; use super::totpmodal::TotpModalApp; - -use uuid::Uuid; +use crate::error::*; +use crate::{models, utils}; #[derive(PartialEq, Eq, Properties)] pub struct ModalProps { diff --git a/kanidmd_web_ui/src/credential/totpmodal.rs b/kanidmd_web_ui/src/credential/totpmodal.rs index 0ad6920fa..3616ea04c 100644 --- a/kanidmd_web_ui/src/credential/totpmodal.rs +++ b/kanidmd_web_ui/src/credential/totpmodal.rs @@ -1,21 +1,18 @@ -use crate::error::*; -use crate::utils; - -use super::eventbus::{EventBus, EventBusMsg}; -use super::reset::ModalProps; - #[cfg(debug)] use gloo::console; -use web_sys::Node; +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, RequestInit, RequestMode, Response}; use yew::prelude::*; use yew_agent::Dispatched; -use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; -use wasm_bindgen_futures::JsFuture; -use web_sys::{Request, RequestInit, RequestMode, Response}; - -use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret}; -use qrcode::{render::svg, QrCode}; +use super::eventbus::{EventBus, EventBusMsg}; +use super::reset::ModalProps; +use crate::error::*; +use crate::utils; enum TotpState { Init, diff --git a/kanidmd_web_ui/src/error.rs b/kanidmd_web_ui/src/error.rs index 538c6284c..f24725c32 100644 --- a/kanidmd_web_ui/src/error.rs +++ b/kanidmd_web_ui/src/error.rs @@ -1,5 +1,6 @@ use std::error::Error; use std::fmt; + use wasm_bindgen::JsValue; #[derive(Debug, Clone, PartialEq)] diff --git a/kanidmd_web_ui/src/login.rs b/kanidmd_web_ui/src/login.rs index 974eae65b..681cd831f 100644 --- a/kanidmd_web_ui/src/login.rs +++ b/kanidmd_web_ui/src/login.rs @@ -1,5 +1,9 @@ // use anyhow::Error; use gloo::console; +use kanidm_proto::v1::{ + AuthAllowed, AuthCredential, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep, +}; +use kanidm_proto::webauthn::PublicKeyCredential; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_futures::{spawn_local, JsFuture}; @@ -10,13 +14,7 @@ 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; -use crate::utils; - -use kanidm_proto::v1::{ - AuthAllowed, AuthCredential, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep, -}; -use kanidm_proto::webauthn::PublicKeyCredential; +use crate::{models, utils}; pub struct LoginApp { inputvalue: String, diff --git a/kanidmd_web_ui/src/manager.rs b/kanidmd_web_ui/src/manager.rs index de6b9e32e..2adeeb228 100644 --- a/kanidmd_web_ui/src/manager.rs +++ b/kanidmd_web_ui/src/manager.rs @@ -5,6 +5,7 @@ //! will allow you to proceed with the oauth flow. use gloo::console; +use serde::{Deserialize, Serialize}; use wasm_bindgen::UnwrapThrowExt; use yew::functional::*; use yew::prelude::*; @@ -14,7 +15,6 @@ use crate::credential::reset::CredentialResetApp; use crate::login::LoginApp; use crate::oauth2::Oauth2App; use crate::views::{ViewRoute, ViewsApp}; -use serde::{Deserialize, Serialize}; // router to decide on state. #[derive(Routable, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] diff --git a/kanidmd_web_ui/src/models/mod.rs b/kanidmd_web_ui/src/models/mod.rs index 066a8ff8e..c3d6e2e88 100644 --- a/kanidmd_web_ui/src/models/mod.rs +++ b/kanidmd_web_ui/src/models/mod.rs @@ -1,18 +1,16 @@ -use kanidm_proto::oauth2::AuthorisationRequest; - #[cfg(debug)] use gloo::console; -use gloo::storage::LocalStorage as PersistentStorage; -use gloo::storage::SessionStorage as TemporaryStorage; -use gloo::storage::Storage; +use gloo::storage::{ + LocalStorage as PersistentStorage, SessionStorage as TemporaryStorage, Storage, +}; +use kanidm_proto::oauth2::AuthorisationRequest; +use kanidm_proto::v1::{CUSessionToken, CUStatus}; +use serde::{Deserialize, Serialize}; use wasm_bindgen::UnwrapThrowExt; use yew_router::prelude::{AnyHistory, History}; use crate::manager::Route; use crate::views::ViewRoute; -use serde::{Deserialize, Serialize}; - -use kanidm_proto::v1::{CUSessionToken, CUStatus}; pub fn get_bearer_token() -> Option { let prev_session: Result = PersistentStorage::get("kanidm_bearer_token"); diff --git a/kanidmd_web_ui/src/oauth2.rs b/kanidmd_web_ui/src/oauth2.rs index 1f20407bd..4c5e45d84 100644 --- a/kanidmd_web_ui/src/oauth2.rs +++ b/kanidmd_web_ui/src/oauth2.rs @@ -1,8 +1,10 @@ // use anyhow::Error; use gloo::console; -use wasm_bindgen::JsCast; -use wasm_bindgen::JsValue; -use wasm_bindgen::UnwrapThrowExt; +pub use kanidm_proto::oauth2::{ + AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, AuthorisationResponse, + CodeChallengeMethod, ErrorResponse, +}; +use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, RequestRedirect, Response}; use yew::prelude::*; @@ -10,13 +12,7 @@ use yew_router::prelude::*; use crate::error::*; use crate::manager::Route; -use crate::models; -use crate::utils; - -pub use kanidm_proto::oauth2::{ - AccessTokenRequest, AccessTokenResponse, AuthorisationRequest, AuthorisationResponse, - CodeChallengeMethod, ErrorResponse, -}; +use crate::{models, utils}; enum State { // We don't have a token, or something is invalid. diff --git a/kanidmd_web_ui/src/views/apps.rs b/kanidmd_web_ui/src/views/apps.rs index 878e9b5e9..2a9ae6f7b 100644 --- a/kanidmd_web_ui/src/views/apps.rs +++ b/kanidmd_web_ui/src/views/apps.rs @@ -1,9 +1,10 @@ -use crate::components::alpha_warning_banner; -use crate::constants::{CSS_CELL, CSS_PAGE_HEADER, CSS_TABLE}; #[cfg(debug)] use gloo::console; use yew::prelude::*; +use crate::components::alpha_warning_banner; +use crate::constants::{CSS_CELL, CSS_PAGE_HEADER, CSS_TABLE}; + pub enum Msg { // Nothing } diff --git a/kanidmd_web_ui/src/views/mod.rs b/kanidmd_web_ui/src/views/mod.rs index 3ad1aac11..315ca1afa 100644 --- a/kanidmd_web_ui/src/views/mod.rs +++ b/kanidmd_web_ui/src/views/mod.rs @@ -1,18 +1,19 @@ -use crate::components::{admin_accounts, admin_groups, admin_oauth2, adminmenu}; -use crate::error::*; -use crate::manager::Route; -use crate::models; -use crate::utils; +use std::str::FromStr; + use compact_jwt::{Jws, JwsUnverified}; use kanidm_proto::v1::UserAuthToken; use serde::{Deserialize, Serialize}; -use std::str::FromStr; use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; use yew::prelude::*; use yew_router::prelude::*; +use crate::components::{admin_accounts, admin_groups, admin_oauth2, adminmenu}; +use crate::error::*; +use crate::manager::Route; +use crate::{models, utils}; + mod apps; mod components; mod profile; @@ -339,6 +340,7 @@ impl ViewsApp { } } + async fn check_token_valid(token: String) -> Result { let mut opts = RequestInit::new(); opts.method("GET"); diff --git a/kanidmd_web_ui/src/views/profile.rs b/kanidmd_web_ui/src/views/profile.rs index 215499ed1..d68801137 100644 --- a/kanidmd_web_ui/src/views/profile.rs +++ b/kanidmd_web_ui/src/views/profile.rs @@ -1,10 +1,10 @@ -use crate::constants::CSS_PAGE_HEADER; -use crate::views::ViewProps; - use gloo::console; use wasm_bindgen::UnwrapThrowExt; use yew::prelude::*; +use crate::constants::CSS_PAGE_HEADER; +use crate::views::ViewProps; + // User Profile UI pub struct ProfileApp {} diff --git a/kanidmd_web_ui/src/views/security.rs b/kanidmd_web_ui/src/views/security.rs index f19b539c9..33d3083f3 100644 --- a/kanidmd_web_ui/src/views/security.rs +++ b/kanidmd_web_ui/src/views/security.rs @@ -1,24 +1,21 @@ -use crate::constants::CSS_PAGE_HEADER; -use crate::error::*; -use crate::models; -use crate::utils; - -use crate::components::change_unix_password::ChangeUnixPassword; -use crate::manager::Route; -use crate::views::{ViewProps, ViewRoute}; +use std::str::FromStr; use compact_jwt::{Jws, JwsUnverified}; #[cfg(debug)] use gloo::console; -use std::str::FromStr; -use yew::prelude::*; -use yew_router::prelude::*; - use kanidm_proto::v1::{CUSessionToken, CUStatus, UiHint, UserAuthToken}; - use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; +use yew::prelude::*; +use yew_router::prelude::*; + +use crate::components::change_unix_password::ChangeUnixPassword; +use crate::constants::CSS_PAGE_HEADER; +use crate::error::*; +use crate::manager::Route; +use crate::views::{ViewProps, ViewRoute}; +use crate::{models, utils}; #[allow(clippy::large_enum_variant)] // Page state diff --git a/orca/Cargo.toml b/orca/Cargo.toml index dd5864809..37698aede 100644 --- a/orca/Cargo.toml +++ b/orca/Cargo.toml @@ -1,44 +1,44 @@ [package] name = "orca" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.59" -edition = "2021" -license = "MPL-2.0" description = "Orca - load testing for LDAP and Kanidm" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +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 = { version = "^3.2", features = ["derive"] } -crossbeam = "0.8.1" -csv = "1.1.6" -dialoguer = "0.10.1" -futures-util = { version = "^0.3.21", features = ["sink"] } -kanidm_client = { path = "../kanidm_client" } -kanidm_proto = { path = "../kanidm_proto" } -ldap3_proto = "^0.2.3" -mathru = "^0.13.0" -openssl = "^0.10.41" -rand = "^0.8.5" -serde = { version = "^1.0.142", features = ["derive"] } -serde_json = "^1.0.83" -tokio = { version = "^1.21.1", features = ["rt-multi-thread"] } -tokio-openssl = "^0.6.3" -tokio-util = { version = "^0.7.4", features = ["codec"] } -toml = "^0.5.9" -tracing = "^0.1.35" -tracing-subscriber = "^0.3.14" -uuid = { version = "^1.1.2", features = ["serde", "v4" ] } +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 +serde = { workspace = true, features = ["derive"] } +serde_json.workspace = true +tokio = { workspace = true, features = ["rt-multi-thread"] } +tokio-openssl.workspace = true +tokio-util = { workspace = true, features = ["codec"] } +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 = "0.5" - +tikv-jemallocator.workspace = true [build-dependencies] -profiles = { path = "../profiles" } +profiles.workspace = true diff --git a/orca/src/data.rs b/orca/src/data.rs index f0ad49458..665b1994d 100644 --- a/orca/src/data.rs +++ b/orca/src/data.rs @@ -1,10 +1,10 @@ use std::collections::{HashMap, HashSet}; use std::time::Duration; -use uuid::Uuid; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; +use uuid::Uuid; pub fn readable_password_from_random() -> String { let mut trng = thread_rng(); diff --git a/orca/src/ds.rs b/orca/src/ds.rs index fa8db1979..5239ef54b 100644 --- a/orca/src/ds.rs +++ b/orca/src/ds.rs @@ -1,11 +1,13 @@ +use std::collections::{HashMap, HashSet}; +use std::time::{Duration, Instant}; + +use ldap3_proto::proto::*; +use uuid::Uuid; + use crate::data::*; use crate::ldap::{LdapClient, LdapSchema}; use crate::profile::DsConfig; use crate::{TargetServer, TargetServerBuilder}; -use ldap3_proto::proto::*; -use std::collections::{HashMap, HashSet}; -use std::time::{Duration, Instant}; -use uuid::Uuid; #[derive(Debug)] pub struct DirectoryServer { diff --git a/orca/src/kani.rs b/orca/src/kani.rs index 75e57c319..a35a698ae 100644 --- a/orca/src/kani.rs +++ b/orca/src/kani.rs @@ -1,12 +1,14 @@ +use std::collections::{HashMap, HashSet}; +use std::time::{Duration, Instant}; + +use kanidm_client::{ClientError, KanidmClient, KanidmClientBuilder, StatusCode}; +use kanidm_proto::v1::*; +use uuid::Uuid; + use crate::data::*; use crate::ldap::{LdapClient, LdapSchema}; use crate::profile::{KaniHttpConfig, KaniLdapConfig}; use crate::{TargetServer, TargetServerBuilder}; -use kanidm_client::{ClientError, KanidmClient, KanidmClientBuilder, StatusCode}; -use kanidm_proto::v1::*; -use std::collections::{HashMap, HashSet}; -use std::time::{Duration, Instant}; -use uuid::Uuid; #[derive(Debug)] pub struct KaniHttpServer { diff --git a/orca/src/ldap.rs b/orca/src/ldap.rs index d4ba09870..1079ac54b 100644 --- a/orca/src/ldap.rs +++ b/orca/src/ldap.rs @@ -1,9 +1,11 @@ +use core::pin::Pin; use std::net::{SocketAddr, ToSocketAddrs}; use std::time::{Duration, Instant}; -use core::pin::Pin; use futures_util::sink::SinkExt; use futures_util::stream::StreamExt; +use ldap3_proto::proto::*; +use ldap3_proto::LdapCodec; use openssl::ssl::{Ssl, SslConnector, SslMethod, SslVerifyMode}; // use std::sync::atomic::{AtomicUsize, Ordering}; use tokio::net::TcpStream; @@ -11,9 +13,6 @@ use tokio::sync::Mutex; use tokio_openssl::SslStream; use tokio_util::codec::Framed; -use ldap3_proto::proto::*; -use ldap3_proto::LdapCodec; - struct LdapInner { pub framed: Framed, LdapCodec>, pub msgid: i32, diff --git a/orca/src/main.rs b/orca/src/main.rs index 218b8d63d..890411d97 100644 --- a/orca/src/main.rs +++ b/orca/src/main.rs @@ -15,14 +15,16 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[macro_use] extern crate tracing; -use crate::ds::DirectoryServer; -use crate::kani::{KaniHttpServer, KaniLdapServer}; -use clap::{Parser, Subcommand}; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::time::{Duration, Instant}; + +use clap::{Parser, Subcommand}; use uuid::Uuid; +use crate::ds::DirectoryServer; +use crate::kani::{KaniHttpServer, KaniLdapServer}; + mod data; mod ds; mod kani; diff --git a/orca/src/preprocess.rs b/orca/src/preprocess.rs index 1e6cc196b..24ca190e3 100644 --- a/orca/src/preprocess.rs +++ b/orca/src/preprocess.rs @@ -1,7 +1,3 @@ -use crate::data::*; -use rand::seq::SliceRandom; -use rand::Rng; -use serde::Deserialize; use std::cmp::Ordering; use std::collections::{BTreeMap, HashMap, HashSet}; use std::convert::TryFrom; @@ -10,8 +6,14 @@ use std::io::BufReader; use std::path::Path; use std::str::FromStr; use std::time::Duration; + +use rand::seq::SliceRandom; +use rand::Rng; +use serde::Deserialize; use uuid::Uuid; +use crate::data::*; + #[derive(Debug, Deserialize)] struct RawRecord { conn: String, diff --git a/orca/src/runner/mod.rs b/orca/src/runner/mod.rs index d35efec3d..76d592291 100644 --- a/orca/src/runner/mod.rs +++ b/orca/src/runner/mod.rs @@ -1,8 +1,10 @@ -use crate::setup::config; -use crate::{TargetOpt, TestTypeOpt}; -use dialoguer::Confirm; use std::fs::create_dir_all; use std::path::{Path, PathBuf}; + +use dialoguer::Confirm; + +use crate::setup::config; +use crate::{TargetOpt, TestTypeOpt}; mod search; pub(crate) async fn doit( diff --git a/orca/src/runner/search.rs b/orca/src/runner/search.rs index b00730ba1..a31f63c68 100644 --- a/orca/src/runner/search.rs +++ b/orca/src/runner/search.rs @@ -1,20 +1,20 @@ -use crate::data::{Entity, OpType, TestData}; -use crate::profile::Profile; -use crate::{TargetServer, TargetServerBuilder}; -use crossbeam::channel::{unbounded, RecvTimeoutError}; -use mathru::statistics::distrib::Continuous; -use mathru::statistics::distrib::Normal; -use rand::seq::IteratorRandom; -use rand::seq::SliceRandom; -use serde::{Deserialize, Serialize}; use std::fs::File; use std::io::BufWriter; use std::path::PathBuf; use std::sync::Arc; use std::time::{Duration, Instant}; + +use crossbeam::channel::{unbounded, RecvTimeoutError}; +use mathru::statistics::distrib::{Continuous, Normal}; +use rand::seq::{IteratorRandom, SliceRandom}; +use serde::{Deserialize, Serialize}; use tokio::sync::broadcast; use tokio::task; +use crate::data::{Entity, OpType, TestData}; +use crate::profile::Profile; +use crate::{TargetServer, TargetServerBuilder}; + #[derive(Debug, Clone)] enum TestPhase { WarmUp, diff --git a/orca/src/setup.rs b/orca/src/setup.rs index b8a5c8210..2bb23bcd6 100644 --- a/orca/src/setup.rs +++ b/orca/src/setup.rs @@ -1,14 +1,14 @@ +use std::fs::File; +use std::io::{BufReader, Read}; +use std::path::{Path, PathBuf}; + +use uuid::Uuid; + use crate::data::TestData; use crate::ds::DirectoryServer; use crate::kani::{KaniHttpServer, KaniLdapServer}; use crate::profile::Profile; -use crate::TargetOpt; -use crate::TargetServer; -use std::fs::File; -use std::io::BufReader; -use std::io::Read; -use std::path::{Path, PathBuf}; -use uuid::Uuid; +use crate::{TargetOpt, TargetServer}; pub(crate) fn config( target: &TargetOpt, diff --git a/profiles/Cargo.toml b/profiles/Cargo.toml index 5ea1b10f6..bde4c7c98 100644 --- a/profiles/Cargo.toml +++ b/profiles/Cargo.toml @@ -1,23 +1,24 @@ [package] name = "profiles" -version = "1.1.0-alpha.9" -authors = ["William Brown "] -rust-version = "1.64" -edition = "2021" -license = "MPL-2.0" description = "Kanidm Build System Profiles" documentation = "https://docs.rs/kanidm/latest/kanidm/" -homepage = "https://github.com/kanidm/kanidm/" -repository = "https://github.com/kanidm/kanidm/" + +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" path = "src/lib.rs" [dependencies] -serde = { version = "^1.0.142", features = ["derive"] } -toml = "^0.5.9" -base64 = "^0.13.0" +serde = { workspace = true, features = ["derive"] } +toml.workspace = true +base64.workspace = true [build-dependencies] -base64 = "^0.13.0" +base64.workspace = true diff --git a/profiles/build.rs b/profiles/build.rs index 6fc63d576..115b2c1e0 100644 --- a/profiles/build.rs +++ b/profiles/build.rs @@ -1,6 +1,5 @@ -use std::env; -use std::fs; use std::path::PathBuf; +use std::{env, fs}; fn main() { println!("cargo:rerun-if-env-changed=KANIDM_BUILD_PROFILE"); diff --git a/profiles/src/lib.rs b/profiles/src/lib.rs index 6b692d060..27858e728 100644 --- a/profiles/src/lib.rs +++ b/profiles/src/lib.rs @@ -1,6 +1,7 @@ -use serde::Deserialize; use std::env; +use serde::Deserialize; + #[derive(Debug, Deserialize)] #[allow(non_camel_case_types)] enum CpuOptLevel { diff --git a/sketching/Cargo.toml b/sketching/Cargo.toml index 4801c4982..a1e9d627b 100644 --- a/sketching/Cargo.toml +++ b/sketching/Cargo.toml @@ -1,18 +1,19 @@ [package] name = "sketching" -version = "0.1.0" -edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +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 = "^0.1.57" -tide = "^0.16.0" -num_enum = "^0.5.7" - -tracing = { version = "^0.1.35", features = ["attributes", "max_level_trace", "release_max_level_debug"] } -tracing-subscriber = { version = "^0.3.14", features = ["env-filter"] } - -# tracing-forest = { version = "0.1.4", features = ["uuid", "smallvec", "tokio", "env-filter"] } -tracing-forest = { git = "https://github.com/QnnOkabayashi/tracing-forest.git", rev = "48d78f7294ceee47a22eee5c80964143c4fb3fe1", features = ["uuid", "smallvec", "tokio", "env-filter"] } +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"] } diff --git a/sketching/src/lib.rs b/sketching/src/lib.rs index f84d28db5..778e5e21f 100644 --- a/sketching/src/lib.rs +++ b/sketching/src/lib.rs @@ -2,14 +2,13 @@ #![warn(unused_extern_crates)] use num_enum::{IntoPrimitive, TryFromPrimitive}; -use tracing_forest::{util::*, Tag}; +use tracing_forest::util::*; +use tracing_forest::Tag; pub mod macros; pub mod middleware; -pub use tracing; -pub use tracing_forest; -pub use tracing_subscriber; +pub use {tracing, tracing_forest, tracing_subscriber}; pub fn test_init() { // tracing_subscriber::fmt::try_init() diff --git a/sketching/src/middleware.rs b/sketching/src/middleware.rs index b6a4b09d3..5dd8c779c 100644 --- a/sketching/src/middleware.rs +++ b/sketching/src/middleware.rs @@ -1,8 +1,7 @@ -use crate::{request_error, request_info, request_warn, security_info}; use tide::{self, Middleware, Next, Request}; use tracing::{self, instrument}; -use crate::*; +use crate::{request_error, request_info, request_warn, security_info, *}; #[derive(Default)] pub struct TreeMiddleware {}