From c021b305f53101764fb8fc1d71cc4bd5e0b3311f Mon Sep 17 00:00:00 2001 From: Noel Date: Wed, 17 Jan 2024 17:19:51 -0800 Subject: [PATCH 01/28] start on moving crates into a central crate (`charted`; ./src folder) --- .github/workflows/UpdateProtos.yaml | 4 +- .gitignore | 46 +- Cargo.lock | 2580 +++++++---------- Cargo.toml | 169 +- build.rs | 82 + protos/emails.proto | 77 + .../google/protobuf/struct.proto | 0 src/auth/mod.rs | 0 src/avatars.rs | 14 + src/bin/main.rs | 16 + src/caching/mod.rs | 111 + src/charts/mod.rs | 14 + src/cli/mod.rs | 0 src/common/as_any.rs | 46 + src/common/bitfield.rs | 201 ++ src/common/mod.rs | 26 + src/common/models/distribution.rs | 186 ++ src/common/models/entities.rs | 324 +++ src/common/models/entities/apikeyscope.rs | 376 +++ .../models/entities/member_permissions.rs | 213 ++ src/common/models/helm.rs | 370 +++ src/common/models/mod.rs | 111 + src/common/models/name.rs | 360 +++ src/common/models/payloads.rs | 281 ++ src/common/os.rs | 40 + src/common/serde.rs | 169 ++ src/common/snowflake.rs | 190 ++ src/common/validators.rs | 30 + src/config/caching.rs | 204 ++ src/config/cdn.rs | 47 + src/config/db.rs | 106 + src/config/logging.rs | 85 + src/config/metrics.rs | 14 + src/config/mod.rs | 184 ++ src/config/redis.rs | 78 + src/config/search.rs | 17 + src/config/search/elasticsearch.rs | 14 + src/config/search/meilisearch.rs | 0 src/config/server.rs | 86 + src/config/server/ratelimits.rs | 14 + src/config/server/ssl.rs | 71 + src/config/sessions.rs | 117 + src/config/sessions/ldap.rs | 182 ++ src/config/sessions/token_server.rs | 72 + src/config/storage.rs | 169 ++ src/db/mod.rs | 0 src/emails.rs | 37 + src/lib.rs | 148 + src/macros.rs | 100 + src/metrics/mod.rs | 0 src/openapi/mod.rs | 0 src/redis.rs | 145 + src/search/mod.rs | 0 src/server/mod.rs | 0 src/sessions/mod.rs | 0 55 files changed, 6318 insertions(+), 1608 deletions(-) mode change 100755 => 100644 Cargo.toml create mode 100644 build.rs create mode 100644 protos/emails.proto rename {crates/emails/protos => protos}/google/protobuf/struct.proto (100%) create mode 100644 src/auth/mod.rs create mode 100644 src/avatars.rs create mode 100644 src/bin/main.rs create mode 100644 src/caching/mod.rs create mode 100644 src/charts/mod.rs create mode 100644 src/cli/mod.rs create mode 100644 src/common/as_any.rs create mode 100644 src/common/bitfield.rs create mode 100644 src/common/mod.rs create mode 100644 src/common/models/distribution.rs create mode 100644 src/common/models/entities.rs create mode 100644 src/common/models/entities/apikeyscope.rs create mode 100644 src/common/models/entities/member_permissions.rs create mode 100644 src/common/models/helm.rs create mode 100644 src/common/models/mod.rs create mode 100644 src/common/models/name.rs create mode 100644 src/common/models/payloads.rs create mode 100644 src/common/os.rs create mode 100644 src/common/serde.rs create mode 100644 src/common/snowflake.rs create mode 100644 src/common/validators.rs create mode 100644 src/config/caching.rs create mode 100644 src/config/cdn.rs create mode 100644 src/config/db.rs create mode 100644 src/config/logging.rs create mode 100644 src/config/metrics.rs create mode 100644 src/config/mod.rs create mode 100644 src/config/redis.rs create mode 100644 src/config/search.rs create mode 100644 src/config/search/elasticsearch.rs create mode 100644 src/config/search/meilisearch.rs create mode 100644 src/config/server.rs create mode 100644 src/config/server/ratelimits.rs create mode 100644 src/config/server/ssl.rs create mode 100644 src/config/sessions.rs create mode 100644 src/config/sessions/ldap.rs create mode 100644 src/config/sessions/token_server.rs create mode 100644 src/config/storage.rs create mode 100644 src/db/mod.rs create mode 100644 src/emails.rs create mode 100644 src/lib.rs create mode 100644 src/macros.rs create mode 100644 src/metrics/mod.rs create mode 100644 src/openapi/mod.rs create mode 100644 src/redis.rs create mode 100644 src/search/mod.rs create mode 100644 src/server/mod.rs create mode 100644 src/sessions/mod.rs diff --git a/.github/workflows/UpdateProtos.yaml b/.github/workflows/UpdateProtos.yaml index 7ab2c9e49..d6c94ede0 100644 --- a/.github/workflows/UpdateProtos.yaml +++ b/.github/workflows/UpdateProtos.yaml @@ -31,8 +31,8 @@ jobs: - name: Update protos run: | - curl -fsSL -o ./crates/emails/protos/google/protobuf/struct.proto ${{env.GOOGLE_PROTOBUF_STRUCT_PROTO}} - curl -fsSL -o ./crates/emails/protos/emails.proto ${{env.CHARTED_EMAILS_PROTO}} + curl -fsSL -o ./protos/google/protobuf/struct.proto ${{env.GOOGLE_PROTOBUF_STRUCT_PROTO}} + curl -fsSL -o ./protos/emails.proto ${{env.CHARTED_EMAILS_PROTO}} - name: Commit! uses: EndBug/add-and-commit@v9 diff --git a/.gitignore b/.gitignore index fe673271d..17fa373ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,48 +1,3 @@ -# Created by https://www.toptal.com/developers/gitignore/api/Bazel,Go,Rust,Node,PNPM,JetBrains+All,VisualStudio,VisualStudioCode,Terraform -# Edit at https://www.toptal.com/developers/gitignore?templates=Bazel,Go,Rust,Node,PNPM,JetBrains+All,VisualStudio,VisualStudioCode,Terraform - -### Bazel ### -# gitignore template for Bazel build system -# website: https://bazel.build/ - -# Ignore all bazel-* symlinks. There is no full list since this can change -# based on the name of the directory bazel is cloned into. -/bazel-* - -# Directories for the Bazel IntelliJ plugin containing the generated -# IntelliJ project files and plugin configuration. Seperate directories are -# for the IntelliJ, Android Studio and CLion versions of the plugin. -/.ijwb/ -/.aswb/ -/.clwb/ - -### Go ### -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work - -### JetBrains+all ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - # User-specific stuff .idea/**/workspace.xml .idea/**/tasks.xml @@ -745,3 +700,4 @@ config.yml data/ docs/ .env +!src/bin/ diff --git a/Cargo.lock b/Cargo.lock index 3d3f0b786..7d97eb085 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "RustyXML" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b5ace29ee3216de37c0546865ad08edef58b0f9e76838ed8959a84a990e58c5" + [[package]] name = "addr2line" version = "0.21.0" @@ -19,12 +25,12 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.12", "once_cell", "version_check", "zerocopy", @@ -39,6 +45,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 = "allocator-api2" version = "0.2.16" @@ -60,20 +81,11 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" dependencies = [ "anstyle", "anstyle-parse", @@ -119,9 +131,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.77" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arc-swap" @@ -148,7 +160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] @@ -158,11 +170,14 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" dependencies = [ + "brotli", "flate2", "futures-core", "memchr", "pin-project-lite", "tokio", + "zstd", + "zstd-safe", ] [[package]] @@ -171,7 +186,18 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -182,7 +208,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -204,18 +230,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] name = "async-trait" -version = "0.1.76" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -234,7 +260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" dependencies = [ "nix 0.27.1", - "rand", + "rand 0.8.5", ] [[package]] @@ -245,9 +271,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aws-config" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11382bd8ac4c6c182a9775990935f96c916a865f1414486595f18eb8cfa9d90b" +checksum = "7e64b72d4bdbb41a73d27709c65a25b6e4bfc8321bf70fa3a8b19ce7d4eb81b0" dependencies = [ "aws-credential-types", "aws-http", @@ -266,8 +292,8 @@ dependencies = [ "fastrand 2.0.1", "hex", "http 0.2.11", - "hyper", - "ring 0.17.7", + "hyper 0.14.28", + "ring", "time", "tokio", "tracing", @@ -276,9 +302,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a1629320d319dc715c6189b172349186557e209d2a7b893ff3d14efd33a47c" +checksum = "4a7cb3510b95492bd9014b60e2e3bee3e48bc516e220316f8e6b60df18b47331" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -288,25 +314,25 @@ dependencies = [ [[package]] name = "aws-http" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e4199d5d62ab09be6a64650c06cc5c4aa45806fed4c74bc4a5c8eaf039a6fa" +checksum = "a95d41abe4e941399fdb4bc2f54713eac3c839d98151875948bb24e66ab658f2" dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "aws-types", "bytes", "http 0.2.11", - "http-body", + "http-body 0.4.6", "pin-project-lite", "tracing", ] [[package]] name = "aws-runtime" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87116d357c905b53f1828d15366363fd27b330a0393cbef349e653f686d36bad" +checksum = "233cca219c6705d525ace011d6f9bc51aaf32fce5b4c41661d2d7ff22d9b4d49" dependencies = [ "aws-credential-types", "aws-http", @@ -326,9 +352,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21392b29994de019a7059af5eab144ea49d572dd52863d8e10537267f59f998c" +checksum = "634fbe5b6591ee2e281cd2ba8641e9bd752dbf5bf338924d6ad4bd5a3304fe31" dependencies = [ "aws-credential-types", "aws-http", @@ -346,7 +372,7 @@ dependencies = [ "aws-types", "bytes", "http 0.2.11", - "http-body", + "http-body 0.4.6", "once_cell", "percent-encoding", "regex-lite", @@ -356,9 +382,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9d9a8ac4cdb8df39f9777fd41e15a9ae0d0b622b00909ae0322b4d2f9e6ac8" +checksum = "ee41005e0f3a19ae749c7953d9e1f1ef8d2183f76f64966e346fa41c1ba0ed44" dependencies = [ "aws-credential-types", "aws-http", @@ -379,9 +405,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ba4a42aa91acecd5ca43b330b5c8eb7f8808d720b6a6f796a35faa302fc73d" +checksum = "fa08168f8a27505e7b90f922c32a489feb1f2133878981a15138bebc849ac09c" dependencies = [ "aws-credential-types", "aws-http", @@ -402,9 +428,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3c7c3dcec7cccd24a13953eedf0f2964c2d728d22112744274cf0098ad2e35" +checksum = "29102eff04d50ef70f11a48823db33e33c6cc5f027bfb6ff4864efbd5f1f66f3" dependencies = [ "aws-credential-types", "aws-http", @@ -426,9 +452,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d222297ca90209dc62245f0a490355795f29de362eb5c19caea4f7f55fe69078" +checksum = "b92384b39aedb258aa734fe0e7b2ffcd13f33e68227251a72cd2635e0acc8f1a" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -444,7 +470,7 @@ dependencies = [ "once_cell", "p256", "percent-encoding", - "ring 0.17.7", + "ring", "sha2", "subtle", "time", @@ -454,9 +480,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9f65000917e3aa94c259d67fe01fa9e4cd456187d026067d642436e6311a81" +checksum = "71d8e1c0904f78c76846a9dad41c28b41d330d97741c3e70d003d9a747d95e2a" dependencies = [ "futures-util", "pin-project-lite", @@ -465,9 +491,9 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2a63681f82fb85ca58d566534b7dc619c782fee0c61c1aa51e2b560c21cb4f" +checksum = "62d59ef74bf94562512e570eeccb81e9b3879f9136b2171ed4bf996ffa609955" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -476,7 +502,7 @@ dependencies = [ "crc32fast", "hex", "http 0.2.11", - "http-body", + "http-body 0.4.6", "md-5", "pin-project-lite", "sha1", @@ -486,9 +512,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85e16fa903c70c49ab3785e5f4ac2ad2171b36e0616f321011fa57962404bb6" +checksum = "31cf0466890a20988b9b2864250dd907f769bd189af1a51ba67beec86f7669fb" dependencies = [ "aws-smithy-types", "bytes", @@ -497,9 +523,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e816425a6b9caea4929ac97d0cb33674849bd5f0086418abc0d02c63f7a1bf" +checksum = "568a3b159001358dd96143378afd7470e19baffb6918e4b5016abe576e553f9c" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -508,7 +534,7 @@ dependencies = [ "bytes-utils", "futures-core", "http 0.2.11", - "http-body", + "http-body 0.4.6", "once_cell", "percent-encoding", "pin-project-lite", @@ -518,18 +544,18 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab3f6d49e08df2f8d05e1bb5b68998e1e67b76054d3c43e7b954becb9a5e9ac" +checksum = "f12bfb23370a069f8facbfd53ce78213461b0a8570f6c81488030f5ab6f8cc4e" dependencies = [ "aws-smithy-types", ] [[package]] name = "aws-smithy-query" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f94a7a3aa509ff9e8b8d80749851d04e5eee0954c43f2e7d6396c4740028737" +checksum = "3b1adc06e0175c175d280267bb8fd028143518013fcb869e1c3199569a2e902a" dependencies = [ "aws-smithy-types", "urlencoding", @@ -537,9 +563,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da5b0a3617390e769576321816112f711c13d7e1114685e022505cf51fe5e48" +checksum = "7cf0f6845d2d97b953cea791b0ee37191c5509f2897ec7eb7580a0e7a594e98b" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -547,10 +573,10 @@ dependencies = [ "aws-smithy-types", "bytes", "fastrand 2.0.1", - "h2", + "h2 0.3.23", "http 0.2.11", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-rustls", "once_cell", "pin-project-lite", @@ -562,9 +588,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2404c9eb08bfe9af255945254d9afc69a367b7ee008b8db75c05e3bca485fc65" +checksum = "47798ba97a33979c80e837519cf837f18fd6df0adb02dd5286a75d9891c6e671" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -578,16 +604,16 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8136605d14ac88f57dc3a693a9f8a4eab4a3f52bc03ff13746f0cd704e97" +checksum = "4e9a85eafeaf783b2408e35af599e8b96f2c49d9a5d13ad3a887fbdefb6bc744" dependencies = [ "base64-simd", "bytes", "bytes-utils", "futures-core", "http 0.2.11", - "http-body", + "http-body 0.4.6", "itoa", "num-integer", "pin-project-lite", @@ -601,25 +627,25 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8f03926587fc881b12b102048bb04305bf7fb8c83e776f0ccc51eaa2378263" +checksum = "5a84bee2b44c22cbba59f12c34b831a97df698f8e43df579b35998652a00dc13" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5d5ee29077e0fcd5ddd0c227b521a33aaf02434b7cdba1c55eec5c1f18ac47" +checksum = "8549aa62c5b7db5c57ab915200ee214b4f5d8f19b29a4a8fa0b3ad3bca1380e3" dependencies = [ "aws-credential-types", "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", "http 0.2.11", - "rustc_version 0.4.0", + "rustc_version", "tracing", ] @@ -630,20 +656,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", - "axum-macros", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", - "headers", "http 0.2.11", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.28", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +dependencies = [ + "async-trait", + "axum-core 0.4.3", + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", "itoa", "matchit", "memchr", "mime", - "multer 2.1.0", + "multer", "percent-encoding", "pin-project-lite", "rustversion", @@ -669,24 +722,140 @@ dependencies = [ "bytes", "futures-util", "http 0.2.11", - "http-body", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper", "tower-layer", "tower-service", "tracing", ] [[package]] -name = "axum-macros" -version = "0.3.8" +name = "axum-server" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62" +checksum = "c1ad46c3ec4e12f4a4b6835e173ba21c25e484c9d02b49770bf006ce5367c036" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.43", + "arc-swap", + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "openssl", + "pin-project-lite", + "tokio", + "tokio-openssl", + "tower", + "tower-service", +] + +[[package]] +name = "azure_core" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70fd680c0d0424a518229b1150922f92653ba2ac933aa000abc8bf1ca08105f7" +dependencies = [ + "async-trait", + "base64 0.21.7", + "bytes", + "dyn-clone", + "futures", + "getrandom 0.2.12", + "hmac", + "http-types", + "log", + "once_cell", + "paste", + "pin-project", + "quick-xml", + "rand 0.8.5", + "reqwest", + "rustc_version", + "serde", + "serde_json", + "sha2", + "time", + "url", + "uuid", +] + +[[package]] +name = "azure_storage" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d3da73bfa09350e1bd6ae2a260806fcf90048c7e78cd2d8f88be60b19a7266" +dependencies = [ + "RustyXML", + "async-lock 3.3.0", + "async-trait", + "azure_core", + "bytes", + "log", + "serde", + "serde_derive", + "time", + "url", + "uuid", +] + +[[package]] +name = "azure_storage_blobs" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "149c21834a4105d761e3dd33d91c2a3064acc05a3c978848ea8089102ae45c94" +dependencies = [ + "RustyXML", + "azure_core", + "azure_storage", + "azure_svc_blobstorage", + "bytes", + "futures", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", + "uuid", +] + +[[package]] +name = "azure_svc_blobstorage" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c888b7bf522d5405218b8613bf0fae7ddaae6ef3bf4ad42ae005993c96ab8b" +dependencies = [ + "azure_core", + "bytes", + "futures", + "log", + "once_cell", + "serde", + "serde_json", + "time", ] [[package]] @@ -712,15 +881,15 @@ checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" [[package]] name = "base64" -version = "0.11.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64-simd" @@ -738,12 +907,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" - [[package]] name = "bitflags" version = "1.3.2" @@ -778,43 +941,24 @@ dependencies = [ ] [[package]] -name = "bollard" -version = "0.15.0" +name = "brotli" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03db470b3c0213c47e978da93200259a1eb4dae2e5512cba9955e2b540a6fc6" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" dependencies = [ - "base64 0.21.5", - "bollard-stubs", - "bytes", - "futures-core", - "futures-util", - "hex", - "http 0.2.11", - "hyper", - "hyperlocal", - "log", - "pin-project-lite", - "serde", - "serde_derive", - "serde_json", - "serde_repr", - "serde_urlencoded", - "thiserror", - "tokio", - "tokio-util", - "url", - "winapi", + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", ] [[package]] -name = "bollard-stubs" -version = "1.43.0-rc.2" +name = "brotli-decompressor" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58071e8fd9ec1e930efd28e3a90c1251015872a2ce49f81f36421b86466932e" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" dependencies = [ - "serde", - "serde_repr", - "serde_with 3.4.0", + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] @@ -877,33 +1021,18 @@ checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ "camino", "cargo-platform", - "semver 1.0.20", + "semver", "serde", "serde_json", ] -[[package]] -name = "cargo_toml" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" -dependencies = [ - "serde", - "toml", -] - -[[package]] -name = "castaway" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" - [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] @@ -914,547 +1043,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "charted-avatars" -version = "0.0.0-devel.0" -dependencies = [ - "bytes", - "charted-common", - "charted-storage", - "eyre", - "remi-core", - "reqwest", - "tracing", -] - -[[package]] -name = "charted-cache-worker" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-common", - "charted-config", - "charted-redis", - "eyre", - "futures-util", - "moka", - "redis", - "serde", - "serde_json", - "tracing", -] - -[[package]] -name = "charted-cli" -version = "0.0.0-devel.0" +name = "charted" +version = "0.1.0-beta" dependencies = [ - "ansi_term", + "argon2", + "async-recursion", "async-trait", - "charted-common", - "charted-config", - "charted-database", - "charted-logging", - "charted-server", + "aws-sdk-s3", + "axum 0.7.4", + "axum-server", + "azure_storage", + "base64 0.21.7", "chrono", "clap", "clap_complete", "cli-table", "color-eyre", - "dotenv", + "cron", + "dotenvy", + "erased-serde", "eyre", + "flate2", + "futures-util", + "hex", + "humantime", + "iterutils", + "jsonwebtoken", + "ldap3", + "md-5", "mimalloc", + "mime", + "moka", + "multer", + "noelware-config", + "noelware-log", + "noelware-remi", + "noelware-serde", "num_cpus", + "once_cell", "openssl", + "prometheus-client", "promptly", + "prost", + "prost-types", + "rand 0.8.5", + "redis", + "regex", + "remi", + "remi-azure", + "remi-fs", + "remi-s3", + "reqwest", + "rust-embed", + "rustc_version", + "semver", + "sentry", + "sentry-eyre", + "sentry-tower", + "sentry-tracing", + "serde", "serde_json", "serde_yaml", "sqlx", "sysinfo", + "tar", + "tempfile", "tokio", + "tokio-util", + "tonic", + "tonic-build", + "tower", + "tower-http", "tracing", + "tracing-appender", + "tracing-log", + "tracing-opentelemetry", "tracing-subscriber", + "ubyte", "utoipa", -] - -[[package]] -name = "charted-common" -version = "0.0.0-devel.0" -dependencies = [ - "argon2", - "async-trait", - "axum", - "chrono", - "eyre", - "hex", - "humantime", - "md-5", - "once_cell", - "paste", - "rand", - "regex", - "rustc_version 0.4.0", - "semver 1.0.20", - "serde", - "serde_json", - "sqlx", - "thiserror", - "tracing", - "utoipa", + "uuid", "validator", "which 5.0.0", ] -[[package]] -name = "charted-config" -version = "0.0.0-devel.0" -dependencies = [ - "aws-sdk-s3", - "base64 0.21.5", - "charted-common", - "clap", - "eyre", - "lazy_static", - "merge-struct", - "once_cell", - "paste", - "regex", - "remi-fs", - "remi-s3", - "serde", - "serde_yaml", - "thiserror", - "tracing", -] - -[[package]] -name = "charted-database" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-cache-worker", - "charted-common", - "charted-storage", - "eyre", - "sentry", - "serde", - "sqlx", - "tokio", - "tracing", -] - -[[package]] -name = "charted-devtools" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "bollard", - "cargo_toml", - "charted-common", - "charted-logging", - "clap", - "clap_complete", - "color-eyre", - "eyre", - "heck", - "itertools 0.12.0", - "promptly", - "serde", - "serde_json", - "simple_tables", - "tokio", - "toml", - "tracing", - "tracing-subscriber", - "which 5.0.0", -] - -[[package]] -name = "charted-emails-client" -version = "0.0.0-devel.0" -dependencies = [ - "prost", - "prost-types", - "tonic", - "tonic-build", - "tracing", - "which 5.0.0", -] - -[[package]] -name = "charted-features-gc" -version = "0.0.0-devel.0" -dependencies = [ - "logos", - "sentry", - "tracing", -] - -[[package]] -name = "charted-helm-charts" -version = "0.0.0-devel.0" -dependencies = [ - "async-recursion", - "bytes", - "charted-common", - "charted-config", - "charted-storage", - "eyre", - "flate2", - "itertools 0.12.0", - "multer 3.0.0", - "once_cell", - "regex", - "remi-core", - "remi-fs", - "semver 1.0.20", - "sentry", - "serde_yaml", - "tar", - "tempfile", - "tokio", - "tracing", -] - -[[package]] -name = "charted-helm-plugin" -version = "0.0.0-devel.0" -dependencies = [ - "ansi_term", - "async-trait", - "charted-common", - "charted-logging", - "chrono", - "clap", - "clap_complete", - "color-eyre", - "dirs", - "dotenv", - "eyre", - "once_cell", - "reqwest", - "serde", - "serde_json", - "serde_yaml", - "sysinfo", - "tokio", - "tracing", - "tracing-subscriber", - "url", - "which 5.0.0", -] - -[[package]] -name = "charted-logging" -version = "0.0.0-devel.0" -dependencies = [ - "ansi_term", - "charted-config", - "chrono", - "sentry-tracing 0.32.1", - "serde_json", - "tracing", - "tracing-log", - "tracing-subscriber", -] - -[[package]] -name = "charted-metrics" -version = "0.0.0-devel.0" -dependencies = [ - "charted-common", - "charted-config", - "dyn-clone", - "erased-serde", - "prometheus-client", - "serde", - "tokio", -] - -[[package]] -name = "charted-openapi" -version = "0.0.0-devel.0" -dependencies = [ - "charted-common", - "charted-config", - "charted-openapi-proc-macro", - "once_cell", - "utoipa", -] - -[[package]] -name = "charted-openapi-proc-macro" -version = "0.0.0-devel.0" -dependencies = [ - "charted-proc-macros", - "proc-macro2", - "quote", - "syn 2.0.43", - "utoipa", -] - -[[package]] -name = "charted-proc-macros" -version = "0.0.0-devel.0" -dependencies = [ - "axum", - "charted-common", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.43", - "utoipa", -] - -[[package]] -name = "charted-redis" -version = "0.0.0-devel.0" -dependencies = [ - "async-recursion", - "charted-config", - "eyre", - "redis", - "tokio", - "tracing", -] - -[[package]] -name = "charted-search" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-common", - "eyre", - "once_cell", - "serde", -] - -[[package]] -name = "charted-search-elasticsearch" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-common", - "charted-config", - "charted-search", - "elasticsearch", - "eyre", - "once_cell", - "serde", - "serde_json", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "charted-search-meilisearch" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-common", - "charted-config", - "charted-search", - "eyre", - "meilisearch-sdk", - "serde", - "tracing", -] - -[[package]] -name = "charted-server" -version = "0.0.0-devel.0" -dependencies = [ - "ansi_term", - "argon2", - "async-trait", - "axum", - "base64 0.21.5", - "charted-avatars", - "charted-cache-worker", - "charted-common", - "charted-config", - "charted-database", - "charted-helm-charts", - "charted-logging", - "charted-metrics", - "charted-openapi", - "charted-proc-macros", - "charted-redis", - "charted-search", - "charted-search-elasticsearch", - "charted-search-meilisearch", - "charted-server-proc-macro", - "charted-sessions", - "charted-sessions-local", - "charted-storage", - "charted-testkit", - "chrono", - "erased-serde", - "eyre", - "futures-util", - "jsonwebtoken 9.2.0", - "mime", - "multer 3.0.0", - "once_cell", - "paste", - "prometheus-client", - "remi-core", - "rust-embed", - "semver 1.0.20", - "sentry", - "sentry-eyre", - "sentry-tower", - "sentry-tracing 0.32.1", - "serde", - "serde_json", - "serde_path_to_error", - "serde_yaml", - "sqlx", - "tokio", - "tower", - "tower-http", - "tower-layer", - "tracing", - "tracing-log", - "tracing-subscriber", - "utoipa", - "validator", -] - -[[package]] -name = "charted-server-proc-macro" -version = "0.0.0-devel.0" -dependencies = [ - "charted-common", - "charted-proc-macros", - "heck", - "proc-macro2", - "quote", - "syn 2.0.43", - "utoipa", -] - -[[package]] -name = "charted-sessions" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-common", - "charted-config", - "charted-redis", - "chrono", - "eyre", - "jsonwebtoken 9.2.0", - "redis", - "sentry", - "serde", - "serde_json", - "sqlx", - "tokio", - "tokio-util", - "tracing", - "utoipa", - "uuid", -] - -[[package]] -name = "charted-sessions-integrations" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "charted-sessions", - "eyre", - "serde", -] - -[[package]] -name = "charted-sessions-integrations-github" -version = "0.0.0-devel.0" -dependencies = [ - "charted-sessions", - "reqwest", - "sentry", - "serde", - "tracing", -] - -[[package]] -name = "charted-sessions-ldap" -version = "0.0.0-devel.0" -dependencies = [ - "charted-config", - "charted-sessions", - "eyre", - "ldap3", - "sentry", - "tokio", - "tracing", -] - -[[package]] -name = "charted-sessions-local" -version = "0.0.0-devel.0" -dependencies = [ - "argon2", - "async-trait", - "charted-common", - "charted-config", - "charted-redis", - "charted-sessions", - "chrono", - "eyre", - "jsonwebtoken 9.2.0", - "once_cell", - "sentry", - "serde_json", - "sqlx", - "tracing", - "uuid", -] - -[[package]] -name = "charted-sessions-passwordless" -version = "0.0.0-devel.0" -dependencies = [ - "charted-emails-client", - "sentry", - "tracing", -] - -[[package]] -name = "charted-storage" -version = "0.0.0-devel.0" -dependencies = [ - "bytes", - "charted-config", - "remi-core", - "remi-fs", - "remi-s3", - "serde", -] - -[[package]] -name = "charted-testkit" -version = "0.0.0-devel.0" -dependencies = [ - "async-trait", - "axum", - "bytes", - "eyre", - "hyper", - "serde", - "serde_json", - "tokio", -] - -[[package]] -name = "charted-testkit-macros" -version = "0.0.0-devel.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.43", -] - [[package]] name = "chrono" version = "0.4.31" @@ -1472,9 +1143,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.12" +version = "4.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "80932e03c33999b9235edb8655bc9df3204adc9887c2f95b50cb1deb9fd54253" dependencies = [ "clap_builder", "clap_derive", @@ -1482,9 +1153,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "d6c0db58c659eef1c73e444d298c27322a1b52f6927d2ad470c0c0f96fa7b8fa" dependencies = [ "anstream", "anstyle", @@ -1494,9 +1165,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.5" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51919c5608a32e34ea1d6be321ad070065e17613e168c5b6977024290f2630b" +checksum = "dfb0d4825b75ff281318c393e8e1b80c4da9fb75a6b1d98547d389d6fe1f48d2" dependencies = [ "clap", ] @@ -1510,7 +1181,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -1526,6 +1197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adfbb116d9e2c4be7011360d0c0bee565712c11e969c9609b25b619366dc379d" dependencies = [ "cli-table-derive", + "csv", "termcolor", "unicode-width", ] @@ -1563,7 +1235,7 @@ dependencies = [ "eyre", "indenter", "once_cell", - "owo-colors", + "owo-colors 3.5.0", "tracing-error", "url", ] @@ -1575,7 +1247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", - "owo-colors", + "owo-colors 3.5.0", "tracing-core", "tracing-error", ] @@ -1615,15 +1287,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -1642,9 +1305,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -1670,7 +1333,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74" dependencies = [ - "rustc_version 0.4.0", + "rustc_version", ] [[package]] @@ -1682,56 +1345,59 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cron" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff76b51e4c068c52bfd2866e1567bee7c567ae8f24ada09fd4307019e25eab7" +dependencies = [ + "chrono", + "nom", + "once_cell", +] + [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.17" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc6598521bb5a83d491e8c1fe51db7296019d2ca3cb93cc6c2a20369a4d78a2" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-bigint" @@ -1740,7 +1406,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -1751,7 +1417,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1766,104 +1432,24 @@ dependencies = [ ] [[package]] -name = "curl" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2 0.4.10", - "winapi", -] - -[[package]] -name = "curl-sys" -version = "0.4.70+curl-8.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0333d8849afe78a4c8102a429a446bfdd055832af071945520e835ae2d841e" -dependencies = [ - "cc", - "libc", - "libnghttp2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "windows-sys 0.48.0", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.14.4" +name = "csv" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] -name = "darling_macro" -version = "0.14.4" +name = "csv-core" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", + "memchr", ] [[package]] @@ -1898,44 +1484,13 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling 0.14.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "derive_builder_core", - "syn 1.0.109", + "powerfmt", + "serde", ] [[package]] @@ -1992,12 +1547,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - [[package]] name = "dotenvy" version = "0.15.7" @@ -2037,26 +1586,6 @@ dependencies = [ "serde", ] -[[package]] -name = "elasticsearch" -version = "8.5.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d9bd57d914cc66ce878f098f63ed7b5d5b64c30644a5adb950b008f874a6c6" -dependencies = [ - "base64 0.11.0", - "bytes", - "dyn-clone", - "lazy_static", - "percent-encoding", - "reqwest", - "rustc_version 0.2.3", - "serde", - "serde_json", - "serde_with 1.14.0", - "url", - "void", -] - [[package]] name = "elliptic-curve" version = "0.12.3" @@ -2071,7 +1600,7 @@ dependencies = [ "generic-array", "group", "pkcs8 0.9.0", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -2100,9 +1629,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adbf0983fe06bd3a5c19c8477a637c2389feb0994eca7a59e3b961054aa7c0a" +checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7" dependencies = [ "serde", ] @@ -2153,6 +1682,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.11" @@ -2195,15 +1745,15 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] [[package]] name = "file-format" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcb859e047d667f798f913a2cd0d5c214b85944d1191efa8146c98888fc557b" +checksum = "865ed54301d7e5136763302a3c9e595317e08a3119e19a078ab1ed269eb18edc" [[package]] name = "filetime" @@ -2374,7 +1924,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -2419,14 +1969,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -2449,15 +2010,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] [[package]] name = "h2" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" dependencies = [ "bytes", "fnv", @@ -2472,6 +2033,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991910e35c615d8cab86b5ab04be67e6ad24d2bf5f4f11fdbbed26da999bbeab" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.0.0", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2497,30 +2077,6 @@ dependencies = [ "hashbrown 0.14.3", ] -[[package]] -name = "headers" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" -dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http 0.2.11", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http 0.2.11", -] - [[package]] name = "heck" version = "0.4.1" @@ -2614,10 +2170,47 @@ dependencies = [ ] [[package]] -name = "http-range-header" -version = "0.3.1" +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.0.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "base64 0.13.1", + "futures-lite", + "infer 0.2.3", + "pin-project-lite", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] [[package]] name = "httparse" @@ -2647,9 +2240,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.23", "http 0.2.11", - "http-body", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -2661,6 +2254,25 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.1", + "http 1.0.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "tokio", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2669,7 +2281,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.11", - "hyper", + "hyper 0.14.28", "log", "rustls", "rustls-native-certs", @@ -2683,7 +2295,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper", + "hyper 0.14.28", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2696,30 +2308,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] [[package]] -name = "hyperlocal" -version = "0.8.0" +name = "hyper-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" +checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" dependencies = [ + "bytes", + "futures-channel", "futures-util", - "hex", - "hyper", - "pin-project", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.1.0", + "pin-project-lite", + "socket2 0.5.5", "tokio", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2738,12 +2355,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.4.0" @@ -2784,7 +2395,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde", ] [[package]] @@ -2798,6 +2408,12 @@ dependencies = [ "serde", ] +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + [[package]] name = "infer" version = "0.15.0" @@ -2820,40 +2436,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] -name = "isahc" -version = "1.7.2" +name = "is-terminal" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "async-channel", - "castaway", - "crossbeam-utils", - "curl", - "curl-sys", - "encoding_rs", - "event-listener", - "futures-lite", - "http 0.2.11", - "log", - "mime", - "once_cell", - "polling", - "slab", - "sluice", - "tracing", - "tracing-futures", - "url", - "waker-fn", + "hermit-abi", + "rustix", + "windows-sys 0.52.0", ] [[package]] -name = "iso8601" -version = "0.6.1" +name = "is_ci" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153" -dependencies = [ - "nom", -] +checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" [[package]] name = "itertools" @@ -2873,6 +2470,12 @@ dependencies = [ "either", ] +[[package]] +name = "iterutils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83842df9b3772441fec891020d9018e3a4980a13419a6ef866c43c39dfe68a9d" + [[package]] name = "itoa" version = "1.0.10" @@ -2880,24 +2483,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] -name = "js-sys" -version = "0.3.66" +name = "jobserver" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ - "wasm-bindgen", + "libc", ] [[package]] -name = "jsonwebtoken" -version = "8.3.0" +name = "js-sys" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ - "base64 0.21.5", - "ring 0.16.20", - "serde", - "serde_json", + "wasm-bindgen", ] [[package]] @@ -2906,10 +2506,10 @@ version = "9.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "js-sys", "pem", - "ring 0.17.7", + "ring", "serde", "serde_json", "simple_asn1", @@ -2960,9 +2560,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libm" @@ -2980,16 +2580,6 @@ dependencies = [ "libc", ] -[[package]] -name = "libnghttp2-sys" -version = "0.1.8+1.55.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fae956c192dadcdb5dace96db71fa0b827333cce7c7b38dc71446f024d8a340" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "libredox" version = "0.0.1" @@ -3012,18 +2602,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-sys" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "linux-raw-sys" version = "0.4.12" @@ -3046,47 +2624,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "logos" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" -dependencies = [ - "logos-derive", -] - -[[package]] -name = "logos-codegen" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax 0.6.29", - "syn 2.0.43", -] - -[[package]] -name = "logos-derive" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" -dependencies = [ - "logos-codegen", -] - -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "match_cfg" version = "0.1.0" @@ -3109,50 +2646,11 @@ dependencies = [ "digest", ] -[[package]] -name = "meilisearch-index-setting-macro" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f2124b55b9cb28e6a08b28854f4e834a51333cbdc2f72935f401efa686c13c" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "meilisearch-sdk" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2257ea8ed24b079c21570f473e58cccc3de23b46cee331fc513fccdc3f1ae5a1" -dependencies = [ - "async-trait", - "either", - "futures", - "futures-io", - "isahc", - "iso8601", - "js-sys", - "jsonwebtoken 8.3.0", - "log", - "meilisearch-index-setting-macro", - "serde", - "serde_json", - "thiserror", - "time", - "uuid", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "yaup", -] - [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -3163,16 +2661,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "merge-struct" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d82012d21e24135b839b6b9bebd622b7ff0cb40071498bc2d066d3a6d04dd4a" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "mimalloc" version = "0.1.39" @@ -3188,16 +2676,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3220,27 +2698,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] [[package]] name = "moka" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f353abec74660d4b8533c2516c86eb062f1ec8ca49a2758f4f2b1b60b06b0c6e" +checksum = "2cebde309854872ea4fcaf4d7c870ad8d5873091c6bfb7ce91fd08ea648f20b0" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", "futures-util", - "log", "once_cell", "parking_lot", "quanta", - "rustc_version 0.4.0", + "rustc_version", "skeptic", "smallvec", "tagptr", @@ -3249,24 +2726,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "multer" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 0.2.11", - "httparse", - "log", - "memchr", - "mime", - "spin 0.9.8", - "version_check", -] - [[package]] name = "multer" version = "3.0.0" @@ -3282,8 +2741,6 @@ dependencies = [ "memchr", "mime", "spin 0.9.8", - "tokio", - "tokio-util", "version_check", ] @@ -3344,6 +2801,59 @@ dependencies = [ "libc", ] +[[package]] +name = "noelware-config" +version = "0.1.0" +source = "git+https://github.com/Noelware/core-rs?rev=41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0#41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0" +dependencies = [ + "noelware-config-derive", +] + +[[package]] +name = "noelware-config-derive" +version = "0.1.0" +source = "git+https://github.com/Noelware/core-rs?rev=41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0#41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "noelware-log" +version = "0.1.0" +source = "git+https://github.com/Noelware/core-rs?rev=41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0#41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0" +dependencies = [ + "chrono", + "owo-colors 4.0.0", + "serde_json", + "tracing", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "noelware-remi" +version = "0.1.0" +source = "git+https://github.com/Noelware/core-rs?rev=41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0#41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0" +dependencies = [ + "bytes", + "remi", + "remi-azure", + "remi-fs", + "remi-s3", +] + +[[package]] +name = "noelware-serde" +version = "0.1.0" +source = "git+https://github.com/Noelware/core-rs?rev=41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0#41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0" +dependencies = [ + "serde", + "tracing", +] + [[package]] name = "nom" version = "7.1.3" @@ -3396,7 +2906,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "smallvec", "zeroize", ] @@ -3480,7 +2990,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -3501,12 +3011,57 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "opentelemetry" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" +dependencies = [ + "futures-core", + "futures-sink", + "indexmap 2.1.0", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f16aec8a98a457a52664d69e0091bac3a0abd18ead9b641cb00202ba4e0efe4" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "once_cell", + "opentelemetry", + "ordered-float", + "percent-encoding", + "rand 0.8.5", + "thiserror", +] + [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + [[package]] name = "os_info" version = "3.7.0" @@ -3536,6 +3091,15 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "owo-colors" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" +dependencies = [ + "supports-color", +] + [[package]] name = "p256" version = "0.11.1" @@ -3583,7 +3147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -3599,7 +3163,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "serde", ] @@ -3645,7 +3209,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -3697,22 +3261,6 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - [[package]] name = "powerfmt" version = "0.2.0" @@ -3727,12 +3275,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -3761,9 +3309,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -3788,7 +3336,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -3827,7 +3375,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.43", + "syn 2.0.48", "tempfile", "which 4.4.2", ] @@ -3842,7 +3390,7 @@ dependencies = [ "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -3867,20 +3415,29 @@ dependencies = [ [[package]] name = "quanta" -version = "0.11.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +checksum = "9ca0b7bac0b97248c40bb77288fc52029cf1459c0461ea1b05ee32ccf011de2c" dependencies = [ "crossbeam-utils", "libc", - "mach2", "once_cell", "raw-cpuid", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "web-sys", "winapi", ] +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.35" @@ -3900,6 +3457,19 @@ dependencies = [ "nibble_vec", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -3907,8 +3477,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -3918,7 +3498,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -3927,16 +3516,25 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.12", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] name = "raw-cpuid" -version = "10.7.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", ] [[package]] @@ -3974,7 +3572,7 @@ dependencies = [ "itoa", "percent-encoding", "pin-project-lite", - "rand", + "rand 0.8.5", "ryu", "sha1_smol", "socket2 0.4.10", @@ -3999,7 +3597,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom", + "getrandom 0.2.12", "libredox", "thiserror", ] @@ -4013,7 +3611,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -4024,7 +3622,7 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -4033,12 +3631,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.2" @@ -4046,51 +3638,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] -name = "remi-core" -version = "0.4.3" +name = "remi" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a99a5777dd57d28504625e2c088bf35838a62d84ef545bb0489b3e97a71a915" +checksum = "83247f07ce229ea31f36926fa9bf2a72dab8031a32ba63bac50154f6694d0aab" dependencies = [ "async-trait", "bytes", - "derive_builder", "futures", ] +[[package]] +name = "remi-azure" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b471d5b5971f623d44433233df5faed143fba02f76ebf77d7693374d369b76" +dependencies = [ + "async-trait", + "azure_core", + "azure_storage", + "azure_storage_blobs", + "bytes", + "futures-util", + "remi", + "serde", + "tracing", +] + [[package]] name = "remi-fs" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ed3e42c17da520748e0bb0fb37d243787d80a8ff88309066746fa6fcf3c748" +checksum = "4f603281d176b4975064df0d30b64479c149ef8716078365f12a2e913354c2f9" dependencies = [ "async-trait", "bytes", - "derive_builder", "dirs", "file-format", "futures", - "infer", - "log", - "remi-core", + "infer 0.15.0", + "remi", "serde", "tokio", + "tracing", ] [[package]] name = "remi-s3" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "738f29219c273711c39e4cbcfd4358151c2165ea9624d2ade5cd629ac4885518" +checksum = "877046f169a9345f9ec778819a77afa376bc1b0729b6e8dbd17ea891e584aeeb" dependencies = [ "async-trait", "aws-config", "aws-credential-types", "aws-sdk-s3", "bytes", - "log", - "remi-core", + "remi", "serde", "tokio", + "tracing", ] [[package]] @@ -4099,16 +3706,15 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "async-compression", - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.23", "http 0.2.11", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-tls", "ipnet", "js-sys", @@ -4129,6 +3735,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "winreg", ] @@ -4144,21 +3751,6 @@ dependencies = [ "zeroize", ] -[[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 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.7" @@ -4166,10 +3758,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom", + "getrandom 0.2.12", "libc", "spin 0.9.8", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.48.0", ] @@ -4186,7 +3778,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8 0.10.2", - "rand_core", + "rand_core 0.6.4", "signature 2.2.0", "spki 0.7.3", "subtle", @@ -4213,7 +3805,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.43", + "syn 2.0.48", "walkdir", ] @@ -4223,7 +3815,6 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665" dependencies = [ - "mime_guess", "sha2", "walkdir", ] @@ -4234,29 +3825,20 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver", ] [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.1", "errno", @@ -4272,7 +3854,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring", "rustls-webpki", "sct", ] @@ -4295,7 +3877,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -4304,8 +3886,8 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -4374,8 +3956,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -4417,45 +3999,28 @@ dependencies = [ [[package]] name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "sentry" -version = "0.31.8" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5" +checksum = "ab18211f62fb890f27c9bb04861f76e4be35e4c2fcbfc2d98afa37aadebb16f1" dependencies = [ "httpdate", - "log", "native-tls", "reqwest", - "sentry-backtrace", + "sentry-backtrace 0.32.1", "sentry-contexts", - "sentry-core 0.31.8", + "sentry-core 0.32.1", "sentry-debug-images", "sentry-panic", - "sentry-tower", - "sentry-tracing 0.31.8", + "sentry-tracing", "tokio", "ureq", ] @@ -4472,17 +4037,29 @@ dependencies = [ "sentry-core 0.31.8", ] +[[package]] +name = "sentry-backtrace" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf018ff7d5ce5b23165a9cbfee60b270a55ae219bc9eebef2a3b6039356dd7e5" +dependencies = [ + "backtrace", + "once_cell", + "regex", + "sentry-core 0.32.1", +] + [[package]] name = "sentry-contexts" -version = "0.31.8" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6436c1bad22cdeb02179ea8ef116ffc217797c028927def303bc593d9320c0d1" +checksum = "1d934df6f9a17b8c15b829860d9d6d39e78126b5b970b365ccbd817bc0fe82c9" dependencies = [ "hostname", "libc", "os_info", - "rustc_version 0.4.0", - "sentry-core 0.31.8", + "rustc_version", + "sentry-core 0.32.1", "uname", ] @@ -4492,9 +4069,7 @@ version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "901f761681f97db3db836ef9e094acdd8756c40215326c194201941947164ef1" dependencies = [ - "log", "once_cell", - "rand", "sentry-types 0.31.8", "serde", "serde_json", @@ -4507,7 +4082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e362d3fb1c5de5124bf1681086eaca7adf6a8c4283a7e1545359c729f9128ff" dependencies = [ "once_cell", - "rand", + "rand 0.8.5", "sentry-types 0.32.1", "serde", "serde_json", @@ -4515,13 +4090,13 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.31.8" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afdb263e73d22f39946f6022ed455b7561b22ff5553aca9be3c6a047fa39c328" +checksum = "d8bca420d75d9e7a8e54a4806bf4fa8a7e9a804e8f2ff05c7c80234168c6ca66" dependencies = [ "findshlibs", "once_cell", - "sentry-core 0.31.8", + "sentry-core 0.32.1", ] [[package]] @@ -4531,44 +4106,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bf7116dfbdedbbe62ac93edca9b453069013aec2a0917c482a526fcbf4d700b" dependencies = [ "eyre", - "sentry-backtrace", + "sentry-backtrace 0.31.8", "sentry-core 0.31.8", ] [[package]] name = "sentry-panic" -version = "0.31.8" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fbf1c163f8b6a9d05912e1b272afa27c652e8b47ea60cb9a57ad5e481eea99" +checksum = "e0224e7a8e2bd8a32d96804acb8243d6d6e073fed55618afbdabae8249a964d8" dependencies = [ - "sentry-backtrace", - "sentry-core 0.31.8", + "sentry-backtrace 0.32.1", + "sentry-core 0.32.1", ] [[package]] name = "sentry-tower" -version = "0.31.8" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e782e369edac4adfc5bf528b27577270bc3e7023c388ebad9db08e1d56b30b" +checksum = "ca654f9bb134581169b51f2dcf713ae0909157121870a0b94e369368f75ab050" dependencies = [ - "http 0.2.11", - "pin-project", - "sentry-core 0.31.8", + "sentry-core 0.32.1", "tower-layer", "tower-service", - "url", -] - -[[package]] -name = "sentry-tracing" -version = "0.31.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82eabcab0a047040befd44599a1da73d3adb228ff53b5ed9795ae04535577704" -dependencies = [ - "sentry-backtrace", - "sentry-core 0.31.8", - "tracing-core", - "tracing-subscriber", ] [[package]] @@ -4577,6 +4137,7 @@ version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "087bed8c616d176a9c6b662a8155e5f23b40dc9e1fa96d0bd5fb56e8636a9275" dependencies = [ + "sentry-backtrace 0.32.1", "sentry-core 0.32.1", "tracing-core", "tracing-subscriber", @@ -4590,7 +4151,7 @@ checksum = "da956cca56e0101998c8688bc65ce1a96f00673a0e58e663664023d4c7911e82" dependencies = [ "debugid", "hex", - "rand", + "rand 0.8.5", "serde", "serde_json", "thiserror", @@ -4607,7 +4168,7 @@ checksum = "fb4f0e37945b7a8ce7faebc310af92442e2d7c5aa7ef5b42fe6daa98ee133f65" dependencies = [ "debugid", "hex", - "rand", + "rand 0.8.5", "serde", "serde_json", "thiserror", @@ -4618,29 +4179,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", @@ -4649,32 +4210,23 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" dependencies = [ "itoa", "serde", ] [[package]] -name = "serde_repr" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.43", -] - -[[package]] -name = "serde_spanned" -version = "0.6.5" +name = "serde_qs" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ + "percent-encoding", "serde", + "thiserror", ] [[package]] @@ -4689,49 +4241,11 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "serde", - "serde_with_macros", -] - -[[package]] -name = "serde_with" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" -dependencies = [ - "base64 0.21.5", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.1.0", - "serde", - "serde_json", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling 0.13.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "serde_yaml" -version = "0.9.29" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ "indexmap 2.1.0", "itoa", @@ -4793,7 +4307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4803,7 +4317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4818,34 +4332,6 @@ dependencies = [ "time", ] -[[package]] -name = "simple_tables" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1248aa113774f3193c5ad090ee8a429005d32fcdb722f114dce7a74356cce4c" -dependencies = [ - "simple_tables-core", - "simple_tables-derive", -] - -[[package]] -name = "simple_tables-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7d16173bdde70a696f9eaf1b49bb38f41ea7445c800ab46e6d8ac08c157551" - -[[package]] -name = "simple_tables-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add2dda7ba63477aabd1ff151a8f570ebbea9c12444d07bf6ec1a7c5858bd0e7" -dependencies = [ - "proc-macro2", - "quote", - "simple_tables-core", - "syn 1.0.109", -] - [[package]] name = "skeptic" version = "0.13.7" @@ -4870,22 +4356,11 @@ dependencies = [ "autocfg", ] -[[package]] -name = "sluice" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" -dependencies = [ - "async-channel", - "futures-core", - "futures-io", -] - [[package]] name = "smallvec" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" [[package]] name = "socket2" @@ -4976,12 +4451,11 @@ dependencies = [ "atoi", "byteorder", "bytes", - "chrono", "crc", "crossbeam-queue", "dotenvy", "either", - "event-listener", + "event-listener 2.5.3", "futures-channel", "futures-core", "futures-intrusive", @@ -5055,11 +4529,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.21.7", "bitflags 2.4.1", "byteorder", "bytes", - "chrono", "crc", "digest", "dotenvy", @@ -5078,7 +4551,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand", + "rand 0.8.5", "rsa", "serde", "sha1", @@ -5098,10 +4571,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.21.7", "bitflags 2.4.1", "byteorder", - "chrono", "crc", "dotenvy", "etcetera", @@ -5118,7 +4590,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand", + "rand 0.8.5", "serde", "serde_json", "sha1", @@ -5138,7 +4610,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" dependencies = [ "atoi", - "chrono", "flume", "futures-channel", "futures-core", @@ -5184,6 +4655,16 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "supports-color" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +dependencies = [ + "is-terminal", + "is_ci", +] + [[package]] name = "syn" version = "1.0.109" @@ -5197,9 +4678,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -5214,9 +4695,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sysinfo" -version = "0.29.11" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" +checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" dependencies = [ "cfg-if", "core-foundation-sys", @@ -5224,7 +4705,7 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "winapi", + "windows", ] [[package]] @@ -5280,31 +4761,31 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -5325,6 +4806,7 @@ checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", + "js-sys", "powerfmt", "serde", "time-core", @@ -5372,12 +4854,10 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2 0.5.5", "tokio-macros", - "tracing", "windows-sys 0.48.0", ] @@ -5399,7 +4879,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -5412,6 +4892,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-openssl" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ffab79df67727f6acf57f1ff743091873c24c579b1e2ce4d8f53e47ded4d63d" +dependencies = [ + "futures-util", + "openssl", + "openssl-sys", + "tokio", +] + [[package]] name = "tokio-retry" version = "0.3.0" @@ -5419,7 +4911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" dependencies = [ "pin-project", - "rand", + "rand 0.8.5", "tokio", ] @@ -5458,40 +4950,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "toml" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" -dependencies = [ - "indexmap 2.1.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - [[package]] name = "tonic" version = "0.10.2" @@ -5500,13 +4958,13 @@ checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" dependencies = [ "async-stream", "async-trait", - "axum", - "base64 0.21.5", + "axum 0.6.20", + "base64 0.21.7", "bytes", - "h2", + "h2 0.3.23", "http 0.2.11", - "http-body", - "hyper", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-timeout", "percent-encoding", "pin-project", @@ -5529,7 +4987,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -5543,7 +5001,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -5554,21 +5012,23 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "0da193277a4e2c33e59e09b5861580c33dd0a637c3883d0fa74ba40c0374af2e" dependencies = [ - "base64 0.21.5", + "async-compression", + "base64 0.21.7", "bitflags 2.4.1", "bytes", "futures-core", "futures-util", - "http 0.2.11", - "http-body", - "http-range-header", - "httpdate", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", "mime", "pin-project-lite", + "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -5598,6 +5058,18 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.27" @@ -5606,7 +5078,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -5630,24 +5102,32 @@ dependencies = [ ] [[package]] -name = "tracing-futures" -version = "0.2.5" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "pin-project", - "tracing", + "log", + "once_cell", + "tracing-core", ] [[package]] -name = "tracing-log" -version = "0.2.0" +name = "tracing-opentelemetry" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" dependencies = [ - "log", + "js-sys", "once_cell", + "opentelemetry", + "opentelemetry_sdk", + "smallvec", + "tracing", "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", ] [[package]] @@ -5682,6 +5162,15 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ubyte" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" +dependencies = [ + "serde", +] + [[package]] name = "uname" version = "0.1.1" @@ -5745,12 +5234,6 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -5763,7 +5246,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "log", "native-tls", "once_cell", @@ -5796,29 +5279,26 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "utoipa" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff05e3bac2c9428f57ade702667753ca3f5cf085e2011fe697de5bfd49aa72d" +checksum = "272ebdfbc99111033031d2f10e018836056e4d2c8e2acda76450ec7974269fa7" dependencies = [ "indexmap 2.1.0", "serde", "serde_json", - "serde_yaml", "utoipa-gen", ] [[package]] name = "utoipa-gen" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0b6f4667edd64be0e820d6631a60433a269710b6ee89ac39525b872b76d61d" +checksum = "d3c9f4d08338c1bfa70dde39412a040a884c6f318b3d09aaaf3437a1e52027fc" dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "regex", - "syn 2.0.43", - "uuid", + "syn 2.0.48", ] [[package]] @@ -5827,7 +5307,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ - "getrandom", + "getrandom 0.2.12", "serde", ] @@ -5891,12 +5371,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "vsimd" version = "0.8.0" @@ -5928,6 +5402,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5936,9 +5416,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -5946,24 +5426,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -5973,9 +5453,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5983,28 +5463,51 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "wasm-streams" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" dependencies = [ "js-sys", "wasm-bindgen", @@ -6072,13 +5575,23 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.0", +] + [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -6213,15 +5726,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" -[[package]] -name = "winnow" -version = "0.5.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c" -dependencies = [ - "memchr", -] - [[package]] name = "winreg" version = "0.50.0" @@ -6234,9 +5738,9 @@ dependencies = [ [[package]] name = "xattr" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys", @@ -6249,16 +5753,6 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" -[[package]] -name = "yaup" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a59e7d27bed43f7c37c25df5192ea9d435a8092a902e02203359ac9ce3e429d9" -dependencies = [ - "serde", - "url", -] - [[package]] name = "zerocopy" version = "0.7.32" @@ -6276,7 +5770,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.48", ] [[package]] @@ -6284,3 +5778,31 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml old mode 100755 new mode 100644 index 56ae30160..931f24c3e --- a/Cargo.toml +++ b/Cargo.toml @@ -15,36 +15,141 @@ [workspace] resolver = "2" -members = [ - "cli", - "crates/avatars", - "crates/caching", - "crates/common", - "crates/config", - "crates/database", - "crates/emails", - "crates/helm-charts", - "crates/logging", - "crates/metrics", - "crates/openapi", - "crates/openapi/proc-macro", - "crates/proc-macros", - "crates/redis", - "crates/search", - "crates/search/elasticsearch", - "crates/search/meilisearch", - "crates/sessions", - "crates/sessions/integrations", - "crates/sessions/integrations/github", - "crates/sessions/ldap", - "crates/sessions/local", - "crates/sessions/passwordless", - "crates/storage", - "features/gc", - "server", - "server/proc-macro", - "testkit", - "testkit/macros", - "tools/devtools", - "tools/helm-plugin", +#members = ["tools/*"] + +[package] +name = "charted" +description = "🐻‍❄️📦 Free, open source, and reliable Helm Chart registry made in Rust" +version = "0.1.0-beta" +documentation = "https://charts.noelware.org/docs" +edition = "2021" +homepage = "https://charts.noelware.org" +license = "Apache-2.0" +publish = true +repository = "https://github.com/charted-dev/charted" +authors = [ + "Noel Towa ", + "Spotlight ", + "Noelware, LLC. ", ] + +[[bin]] +name = "charted" +path = "./src/bin/main.rs" + +[dependencies] +argon2 = "0.5.2" +async-recursion = "1.0.5" +async-trait = "0.1.77" +aws-sdk-s3 = "1.12.0" +axum = { version = "0.7.4", features = ["http2", "multipart"] } +axum-server = { version = "0.6.0", features = ["tls-openssl"] } +azure_storage = "0.19.0" +base64 = "0.21.7" +chrono = { version = "0.4.31", features = ["serde"] } +clap = { version = "4.4.17", features = ["derive", "env"] } +clap_complete = "4.4.7" +cli-table = "0.4.7" +color-eyre = { version = "0.6.2", features = ["issue-url", "tracing-error"] } +cron = "0.12.0" +dotenvy = "0.15.7" +erased-serde = "0.4.2" +eyre = "0.6.11" +flate2 = "1.0.28" +futures-util = "0.3.30" +hex = "0.4.3" +humantime = "2.1.0" +iterutils = "0.1.0" +jsonwebtoken = "9.2.0" +ldap3 = "0.11.3" +md-5 = "0.10.6" +mimalloc = "0.1.39" +mime = "0.3.17" +moka = { version = "0.12.3", features = ["future"] } +multer = "3.0.0" +noelware-config = { git = "https://github.com/Noelware/core-rs", version = "0.1.0", rev = "41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0", features = [ + "derive", +] } +noelware-log = { git = "https://github.com/Noelware/core-rs", version = "0.1.0", rev = "41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0", features = [ + "log", +] } +noelware-remi = { git = "https://github.com/Noelware/core-rs", version = "0.1.0", rev = "41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0", features = [ + "azure", + "fs", + "s3", +] } +noelware-serde = { git = "https://github.com/Noelware/core-rs", version = "0.1.0", rev = "41257fc1eb6d89a4b4c42a1a2727fd13814ff9d0", features = [ + "tracing", +] } +num_cpus = "1.16.0" +once_cell = "1.19.0" +openssl = "0.10.62" +prometheus-client = "0.22.0" +promptly = "0.3.1" +prost = "0.12.3" +prost-types = "0.12.3" +rand = "0.8.5" +redis = { version = "0.24.0", features = [ + "sentinel", + "tokio-comp", + "connection-manager", +] } +regex = "1.10.2" +remi = "0.5.0" +remi-azure = { version = "0.5.0", features = ["serde", "tracing"] } +remi-fs = { version = "0.5.0", features = ["serde", "tracing"] } +remi-s3 = { version = "0.5.0", features = ["serde", "tracing"] } +reqwest = "0.11.23" +rust-embed = "8.2.0" +semver = { version = "1.0.21", features = ["serde"] } +sentry = "0.32.1" +sentry-eyre = "0.1.0" +sentry-tower = "0.32.1" +sentry-tracing = "0.32.1" +serde = { version = "1.0.195", features = ["derive"] } +serde_json = "1.0.111" +serde_yaml = "0.9.30" +sqlx = { version = "0.7.3", features = [ + "postgres", + "runtime-tokio", + "tls-native-tls", +] } +sysinfo = "0.30.5" +tar = "0.4.40" +tokio = { version = "1.35.1", features = [ + "rt", + "rt-multi-thread", + "macros", + "io-util", + "fs", +] } +tokio-util = "0.7.10" +tonic = "0.10.2" +tower = "0.4.13" +tower-http = { version = "0.5.1", features = [ + "compression-full", + "auth", + "cors", + "catch-panic", + "limit", +] } +tracing = "0.1.40" +tracing-appender = "0.2.3" +tracing-log = "0.2.0" +tracing-opentelemetry = "0.22.0" +tracing-subscriber = "0.3.18" +ubyte = { version = "0.10.4", features = ["serde"] } +utoipa = "4.2.0" +uuid = { version = "1.6.1", features = ["serde", "v4"] } +validator = { version = "0.16.1", features = ["derive"] } + +[build-dependencies] +chrono = "0.4.31" +rustc_version = "0.4.0" +tonic-build = "0.10.2" +which = "5.0.0" + +[dev-dependencies] +remi-fs = "0.5.0" +tempfile = "3.9.0" +tokio = "1.35.1" diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..1af22553e --- /dev/null +++ b/build.rs @@ -0,0 +1,82 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use chrono::{DateTime, Utc}; +use std::{ + env::{set_var, var}, + fs, + path::PathBuf, + time::SystemTime, +}; +use tonic_build::compile_protos; +use which::which; + +fn main() { + // if build.rs changes in any way, then re-run it! + println!("cargo:rerun-if-changed=build.rs"); + + // if protos/emails.proto changes in any way, let Cargo know! + println!("cargo:rerun-if-changed=protos/emails.proto"); + + // if migrations/*.sql changes in any way, let Cargo know! + println!("cargo:rerun-if-changed=migrations"); + + let rust_version = rustc_version::version() + .expect("unable to get 'rustc' version") + .to_string(); + + println!("cargo:rustc-env=CHARTED_RUSTC_VERSION={rust_version}"); + + let build_date = { + let now = SystemTime::now(); + let date: DateTime = now.into(); + + date.to_rfc3339() + }; + + println!("cargo:rustc-env=CHARTED_BUILD_DATE={build_date}"); + + // First, we need to get the Git commit hash. There is ways we can do it: + // 1. Find a .git/HEAD file, read where we need to find the file, read the file and `&bytes[0..8]` + // 2. fuck it and ball with `d1cebae` as the dummy hash + let headfile = PathBuf::from(".git").join("HEAD"); + if let Ok(true) = headfile.try_exists() { + // we should expect "ref: ref/heads/" + let contents = fs::read_to_string(&headfile).expect("to read file [.git/HEAD] contents"); + let Some((_, ref_)) = contents.split_once(' ') else { + panic!("expected 'ref: ref/heads/'; received {}", contents); + }; + + // i know this isn't rusty but what could i do better + let mut iter = ref_.split('/'); + let _ = iter.next().expect("to pop 'ref/'"); + let _ = iter.next().expect("to pop 'heads/'"); + let branch = iter.next().expect("full branch"); + let contents = fs::read_to_string(PathBuf::from(".git").join("refs/heads").join(branch.trim())) + .expect("to read file [.git/refs/heads/] contents"); + + println!("cargo:rustc-env=CHARTED_COMMIT_HASH={}", &contents.trim()[0..8]); + } + + // allow Prost to use a detected `protoc` binary from the host if no `$PROTOC` + // is defined as a env variable. + if var("PROTOC").is_err() { + let protoc = which("protoc").expect("`protoc` binary to be available in $PATH"); + set_var("protoc", protoc); + } + + compile_protos("./protos/emails.proto") + .expect("protobuf [./protos/emails.proto] to be compiled by `prost` successfully"); +} diff --git a/protos/emails.proto b/protos/emails.proto new file mode 100644 index 000000000..846cd91ed --- /dev/null +++ b/protos/emails.proto @@ -0,0 +1,77 @@ +// 🐻‍❄️💌 email-service: charted's email service built in Rust that can be connected via gRPC +// Copyright 2023 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package noelware.charted.emails; +option java_multiple_files = true; +option java_package = "org.noelware.charted.emails.protobufs.v1"; + +import "google/protobuf/struct.proto"; + +service Emails { + rpc Send(SendEmailRequest) returns (SendEmailResponse); + rpc Ping(PingRequest) returns (PingResponse); +} + +// Represents a request to ping the server to check if it is alive or not. +message PingRequest {} + +// Represents the response to the Ping call. +message PingResponse { + // Pong! + bool pong = 1; +} + +// Represents a request to send a email +message SendEmailRequest { + // The address to send the content to + string to = 1; + + // The subject of the email + string subject = 2; + + // Optional content to send, this will not be processed by a template + // and will be directly sent. + optional string content = 3; + + // The template name that is available in the ./templates directory. + optional string template = 4; + + // The template context if the template has variables. + optional google.protobuf.Struct context = 5; +} + +// Represents a response from sending a email +message SendEmailResponse { + // If the request was a success or not. If not, the `error_message` property + // will be available, and to see if you can retry with the `should_retry` property. + bool success = 1; + + // Any errors that might've occured. + repeated Error errors = 2; +} + +message Error { + // A machine-readable error code that you can look up for more information + // A list of codes can be found in the [documentation](https://charts.noelware.org/docs/services/emails/latest/api#error-codes). + string code = 1; + + // Human-readable message to indicate on why it failed. + string message = 2; + + // Any extra details that might help on why it failed. + optional google.protobuf.Struct details = 3; +} diff --git a/crates/emails/protos/google/protobuf/struct.proto b/protos/google/protobuf/struct.proto similarity index 100% rename from crates/emails/protos/google/protobuf/struct.proto rename to protos/google/protobuf/struct.proto diff --git a/src/auth/mod.rs b/src/auth/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/avatars.rs b/src/avatars.rs new file mode 100644 index 000000000..6399b2128 --- /dev/null +++ b/src/avatars.rs @@ -0,0 +1,14 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 000000000..5b2bc56df --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,16 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +fn main() {} diff --git a/src/caching/mod.rs b/src/caching/mod.rs new file mode 100644 index 000000000..142a325d5 --- /dev/null +++ b/src/caching/mod.rs @@ -0,0 +1,111 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use eyre::Result; +use serde::{de::DeserializeOwned, Serialize}; +use std::{borrow::Cow, fmt::Display, ops::Deref, time::Duration}; + +/// Default max object size (15mb) +pub const DEFAULT_MAX_OBJECT_SIZE: u64 = 15 * 1024 * 1024; // 15mb + +/// Default [`Duration`] for cached objects. +pub const DEFAULT_TTL_LIFESPAN: Duration = Duration::from_secs(15 * 60); // 15 minutes + +/// Cache key for caching organizations to underpressure the PostgreSQL database. +pub const ORGANIZATIONS: CacheKey = CacheKey(Cow::Borrowed("organizations")); + +/// Cache key for caching repositories to underpressure the PostgreSQL database. +pub const REPOSITORIES: CacheKey = CacheKey(Cow::Borrowed("repositories")); + +/// Cache key for caching ratelimits from HTTP requests +pub const RATELIMITS: CacheKey = CacheKey(Cow::Borrowed("ratelimits")); + +/// Cache key for caching users to underpressure the PostgreSQL database. +pub const USERS: CacheKey = CacheKey(Cow::Borrowed("users")); + +/// Represents a key for a cache object that is stored from Redis or in-memory. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CacheKey(Cow<'static, str>); +impl CacheKey { + /// Creates a new [`CacheKey`] instance. + pub fn new>>(namespace: I) -> CacheKey { + CacheKey(namespace.into()) + } + + /// Conjoins this existing cache key and returns a new one. + pub fn join>(self, key: I) -> CacheKey { + CacheKey(format!("{}:{}", self, key.into()).into()) + } + + /// Converts this [`CacheKey`] into a Redis-related key that can be queried easily. + pub fn as_redis_key(self) -> String { + format!("charted:cache:{}", self) + } +} + +impl Display for CacheKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0) + } +} + +impl Deref for CacheKey { + type Target = Cow<'static, str>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Represents a worker that handles caching routines (like database objects) that +/// can be configured to expire within a certain timeframe. +/// +/// Objects that can be cached are anything that implement [`Serialize`](serde::ser::Serialize) for +/// putting objects in cache, and [`Deserialize`](serde::de::Deserialize) for retrieving cache +/// objects if they are found. +#[async_trait] +pub trait CacheWorker: Send + Sync { + /// Gets a cached object from this worker or `None` if there is no + /// cached object available. + async fn get(&mut self, key: CacheKey) -> Result>; + + /// Reserve a cache object within a given [`CacheKey`], returns a error + /// if the cache key was already inserted into the cache. + async fn put(&mut self, key: CacheKey, obj: Target) -> Result<()>; + + /// Attempts to delete a cache key from the cache if it exists. + async fn delete(&mut self, key: CacheKey) -> Result<()>; +} + +#[cfg(test)] +fn __assert_object_safe() { + struct SomeCacheWorker; + #[async_trait] + impl CacheWorker<()> for SomeCacheWorker { + async fn get(&mut self, _key: CacheKey) -> Result> { + todo!() + } + + async fn put(&mut self, _key: CacheKey, _obj: ()) -> Result<()> { + Ok(()) + } + + async fn delete(&mut self, _key: CacheKey) -> Result<()> { + Ok(()) + } + } + + let _: &dyn CacheWorker<()> = &SomeCacheWorker; +} diff --git a/src/charts/mod.rs b/src/charts/mod.rs new file mode 100644 index 000000000..6399b2128 --- /dev/null +++ b/src/charts/mod.rs @@ -0,0 +1,14 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/src/cli/mod.rs b/src/cli/mod.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/common/as_any.rs b/src/common/as_any.rs new file mode 100644 index 000000000..8e0e0c8cb --- /dev/null +++ b/src/common/as_any.rs @@ -0,0 +1,46 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::any::Any; + +/// Generic trait to implement `as_any` to help aid using [`Any`] +/// easier. +pub trait AsAny: private::Sealed + Any { + /// Transforms a reference of `self` into a reference of `dyn Any`. + fn as_any(&self) -> &dyn Any; +} + +impl AsAny for T { + fn as_any(&self) -> &dyn Any { + self + } +} + +/// Trait to support downcasting, which you can transform +pub trait Cast: private::Sealed + AsAny { + fn cast(&self) -> Option<&T> { + self.as_any().downcast_ref() + } +} + +impl Cast for T {} + +mod private { + use super::AsAny; + + pub trait Sealed {} + + impl Sealed for T {} +} diff --git a/src/common/bitfield.rs b/src/common/bitfield.rs new file mode 100644 index 000000000..6f790130a --- /dev/null +++ b/src/common/bitfield.rs @@ -0,0 +1,201 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::hashmap; +use std::{collections::HashMap, fmt::Display}; + +// #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] +// pub enum BitfieldError { +// #[error("You can't use u64::MAX to add or remove bits!")] +// MaxProvided, + +// #[error("Bit overflow!!")] +// BitOverflow, +// } + +#[derive(Debug)] +pub enum Error { + /// Provided something [`u64::MAX`] or higher. + MaxProvided, + + /// Bits has been overflowed?! + BitOverflow, +} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use Error::*; + + match self { + MaxProvided => f.write_str("provided maximum amount of bits"), + BitOverflow => f.write_str("bit overflow?! D:"), + } + } +} + +impl std::error::Error for Error {} + +/// Represents a field of bits that is used to control RBAC permissions. +#[derive(Debug, Clone)] +pub struct Bitfield<'a> { + flags: HashMap<&'a str, u64>, + bits: u64, +} + +impl<'a> Default for Bitfield<'a> { + fn default() -> Bitfield<'a> { + Bitfield::new(0, hashmap!()) + } +} + +impl<'a> Bitfield<'a> { + /// Creates a new [Bitfield] instance with the given bits + /// and flags. + pub fn new(bits: u64, flags: HashMap<&'a str, u64>) -> Bitfield { + Bitfield { bits, flags } + } + + /// Initialize a 0-bit field with specified flags. + pub fn with_flags(flags: HashMap<&'a str, u64>) -> Bitfield<'a> { + Bitfield { bits: 0, flags } + } + + /// Initializes a new [Bitfield] with the given bits with the same + /// flags, cloned. + pub fn init(&self, bits: u64) -> Bitfield<'a> { + Bitfield { + bits, + flags: self.flags.clone(), + } + } + + /// Returns a borrowed reference of the initialized flags + /// by this bitfield. + pub fn flags(&self) -> &HashMap<&'a str, u64> { + &self.flags + } + + /// Returns a copied value of the bits that are used in this [Bitfield]. + pub fn bits(&self) -> u64 { + self.bits + } + + /// Returns the maximum amount of bits from all the flags' values. + pub fn max_bits(&self) -> u64 { + self.flags.clone().into_values().fold(0, |acc, curr| acc | curr) + } + + /// Adds all of the bits that were registered by the flags into + /// the bitfield. + pub fn add_all(&mut self) { + self.bits |= self.flags.clone().into_values().fold(0, |mut acc, curr| { + acc |= curr; + acc + }); + } + + /// Adds multiple bits into one bit in this bitfield. + pub fn add<'i, I: Iterator>(&mut self, mut bits: I) -> Result<(), Error> { + // Don't do anything if it is empty + let next = bits.next(); + if next.is_none() { + return Ok(()); + } + + let mut add_up_to = 0u64; + add_up_to |= next.unwrap(); + + for bit in bits { + if *bit == u64::MAX { + return Err(Error::MaxProvided); + } + + if *bit > self.max_bits() { + return Err(Error::BitOverflow); + } + + add_up_to |= *bit; + } + + self.bits |= add_up_to; + Ok(()) + } + + /// Adds multiple bits by referencing flags instead of arbitary bits. + pub fn add_from_flags(&mut self, bits: &[String]) -> Result<(), Error> { + let flags = self.flags.clone(); + + self.add(bits.iter().filter_map(|x| flags.get(&*x.to_string()))) + } + + /// Checks if a given bit is in the bitfield or not. + pub fn contains(&self, bit: u64) -> bool { + (self.bits & bit) != 0 + } + + /// Checks if the given flag was a valid flag and if the bit + /// itself by the flag is contained in the bitfield or not. + pub fn contains_flag>(&self, flag: I) -> bool { + match self.flags.get(flag.as_ref()) { + Some(bit) => self.contains(*bit), + None => false, + } + } + + /// Removes a subset of bits from the bitfield itself. This will + /// use [std::cmp::min] if it flows into the negatives. + pub fn remove<'i, I: Iterator>(&mut self, bits: I) { + let mut to_remove = 0u64; + for bit in bits { + to_remove |= *bit; + } + + self.bits &= std::cmp::min(to_remove, 0); + } + + /// Removes a subset of bits from the bitfield via the flags specified. + pub fn remove_from_flags(&mut self, bits: &[String]) { + let flags = self.flags.clone(); + + self.remove(bits.iter().filter_map(|x| flags.get(&*x.to_string()))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::hashmap; + + #[test] + fn bitfield_usage() { + let mut b = Bitfield::new(0, hashmap!("hello" => 1 << 0)); + + // add bits + assert!(b.add([1 << 0].iter()).is_ok()); + assert_eq!(b.bits(), 1); + + let res = b.add_from_flags(&["world".into()]); + assert!(res.is_ok()); + assert_eq!(b.bits(), 1); + + // remove bits + b.remove([1 << 0].iter()); + assert_eq!(b.bits(), 0); + + // add all bits + b.add_all(); + assert_eq!(b.bits(), 1); + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs new file mode 100644 index 000000000..fa04c62ad --- /dev/null +++ b/src/common/mod.rs @@ -0,0 +1,26 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod as_any; +pub use as_any::*; + +mod snowflake; +pub use snowflake::*; + +pub mod bitfield; +pub mod models; +pub mod os; +pub mod serde; +pub mod validators; diff --git a/src/common/models/distribution.rs b/src/common/models/distribution.rs new file mode 100644 index 000000000..917852b61 --- /dev/null +++ b/src/common/models/distribution.rs @@ -0,0 +1,186 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use serde::{Deserialize, Serialize}; +use std::{env::var, fmt::Display, fs, path::PathBuf}; +use tracing::error; +use utoipa::{ + openapi::{ObjectBuilder, RefOr, Schema, SchemaType}, + ToSchema, +}; + +/// Represents the distribution that this instance is running off from. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)] +#[serde(rename_all = "lowercase")] +pub enum Distribution { + /// Running on a Kubernetes cluster, it can also be running + /// from the [official Helm chart](https://charts.noelware.org/~/charted/server). + Kubernetes, + + /// Unknown distribution, be cautious! + #[default] + Unknown, + + /// Running on the official [Docker image](https://cr.noelware.cloud/~/charted/server). + Docker, + + /// Running from the official RPM distribution + /// from [Noelware's Artifacts Registry](https://artifacts.noelware.cloud) + RPM, + + /// Running from the official Debian distribution + /// from [Noelware's Artifacts Registry](https://artifacts.noelware.cloud) + Deb, + + /// Running from the Git repository + Git, +} + +impl Distribution { + fn is_kubernetes() -> bool { + if var("KUBERNETES_SERVICE_HOST").is_ok() { + return true; + } + + let mut has_service_acc_token = false; + let mut has_service_acc_ns = false; + match PathBuf::from("/run/secrets/kubernetes.io/serviceaccount/token").try_exists() { + Ok(true) => { + has_service_acc_token = true; + } + + Ok(false) => {} + Err(e) => { + error!("unable to detect if we are in a Kubernetes pod (tried to read /run/secrets/kubernetes.io/serviceaccount/token): {e}"); + return false; + } + } + + match PathBuf::from("/run/secrets/kubernetes.io/serviceaccount/namespace").try_exists() { + Ok(true) => { + has_service_acc_ns = true; + } + + Ok(false) => {} + Err(e) => { + error!("unable to detect if we are in a Kubernetes pod (tried to read /run/secrets/kubernetes.io/serviceaccount/namespace): {e}"); + return false; + } + } + + let mut has_cluster_local_in_resolv = false; + let resolv_conf = PathBuf::from("/etc/resolv.conf"); + match resolv_conf.try_exists() { + Ok(true) => { + let Ok(contents) = fs::read_to_string(resolv_conf) else { + error!("unable to detect if we are in a Kubernetes pod (tried to read /etc/resolv.conf)"); + return has_service_acc_token && has_service_acc_ns; + }; + + if contents.contains("cluster.local") { + has_cluster_local_in_resolv = true; + } + } + + Ok(false) => {} + Err(e) => { + error!(error = %e, "unable to detect if we are in a Kubernetes pod (tried to read /run/secrets/kubernetes.io/serviceaccount/namespace):"); + return false; + } + } + + (has_service_acc_token && has_service_acc_ns) || has_cluster_local_in_resolv + } + + fn is_docker() -> bool { + let has_dockerenv = match PathBuf::from("/.dockerenv").try_exists() { + Ok(res) => res, + Err(e) => { + error!(error = %e, "unable to detect if we are in a Docker container (tried to stat /.dockerenv):"); + false + } + }; + + let has_docker_cgroup = { + let cgroup = PathBuf::from("/proc/self/cgroup"); + let Ok(contents) = fs::read_to_string(cgroup) else { + error!("unable to detect if we are in a Docker container (tried to read /proc/self/cgroup)"); + return false; + }; + + contents.contains("docker") + }; + + has_dockerenv || has_docker_cgroup + } + + // TODO(@auguwu): should we cache this information? + pub fn detect() -> Distribution { + if Distribution::is_kubernetes() { + return Distribution::Kubernetes; + } + + if Distribution::is_docker() { + return Distribution::Docker; + } + + match var("CHARTED_DISTRIBUTION_KIND") { + Ok(s) => match s.as_str() { + // rpm and deb are automatically set in the systemd service + // so we don't need to do any detection + "rpm" => Distribution::RPM, + "deb" => Distribution::Deb, + + // git is applied when built from source (i.e, ./dev server) + "git" => Distribution::Git, + + // disallow any other value + _ => Distribution::Unknown, + }, + Err(_) => Distribution::Unknown, + } + } +} + +impl<'s> ToSchema<'s> for Distribution { + fn schema() -> (&'s str, RefOr) { + ( + "Distribution", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .description(Some( + "Represents the distribution that this instance is running off from.", + )) + .schema_type(SchemaType::String) + .enum_values(Some(vec!["kubernetes", "docker", "rpm", "deb", "git", "unknown"])) + .default(Some("unknown".into())) + .build(), + )), + ) + } +} + +impl Display for Distribution { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Distribution::Kubernetes => f.write_str("kubernetes"), + Distribution::Docker => f.write_str("docker"), + Distribution::Git => f.write_str("git"), + Distribution::Deb => f.write_str("debian"), + Distribution::RPM => f.write_str("rpm"), + _ => f.write_str("«unknown»"), + } + } +} diff --git a/src/common/models/entities.rs b/src/common/models/entities.rs new file mode 100644 index 000000000..791803576 --- /dev/null +++ b/src/common/models/entities.rs @@ -0,0 +1,324 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod apikeyscope; +mod member_permissions; + +pub use apikeyscope::*; +pub use member_permissions::*; + +use crate::common::{ + models::{helm::ChartType, DateTime, Name}, + snowflake::ID, +}; +use semver::Version; +use serde::{Deserialize, Serialize}; +use sqlx::FromRow; +use utoipa::{ + openapi::{RefOr, Schema}, + ToSchema, +}; + +// only used for Utoipa to use the `ID` schema from snowflake.rs +fn snowflake_schema() -> RefOr { + ID::schema().1 +} + +fn name_schema() -> RefOr { + crate::common::models::Name::schema().1 +} + +/// Represents an account that can own [repositories][Repository] and [organizations][Organizations] +#[derive(Debug, Clone, Default, Serialize, Deserialize, ToSchema, FromRow)] +pub struct User { + /// Whether if this User is a Verified Publisher or not. + #[serde(default)] + pub verified_publisher: bool, + + /// Valid email address that points to a Gravatar avatar, or `null` if it shouldn't use one as the primary avatar + #[serde(default)] + pub gravatar_email: Option, + + /// Short description about this user, can be `null` if none was provided. + #[serde(default)] + pub description: Option, + + /// Unique hash to locate a user's avatar, this also includes the extension that this avatar is, i.e, `png`. + #[serde(default)] + pub avatar_hash: Option, + + /// Date of when this user was registered to this instance + pub created_at: DateTime, + + /// Date of when the server has last updated this user + pub updated_at: DateTime, + + #[serde(skip)] + pub password: Option, + + /// Unique username that can be used to locate this user with the API + pub username: Name, + + #[serde(skip)] + pub email: String, + + /// Whether if this User is an Administrator of this instance + #[serde(default)] + pub admin: bool, + + /// Display name for this user, it should be displayed as '{name} (@{username})' or just '@{username}' if there is no display name + #[serde(default)] + #[schema(schema_with = name_schema)] + pub name: Option, + + /// Unique identifier to locate this user with the API + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +/// Represents a collection of a user's connections that can be used +/// to login from different sources (like GitHub OAuth2) +#[derive(Debug, Clone, Default, ToSchema, Serialize, Deserialize, FromRow)] +pub struct UserConnections { + /// Snowflake ID that was sourced from [Noelware's Accounts System](https://accounts.noelware.org) + #[serde(default)] + pub noelware_account_id: Option, + + /// Account ID that was sourced from Google OAuth2 + #[serde(default)] + pub google_account_id: Option, + + /// Account ID that was sourced from GitHub OAuth2. This can differ from + /// GitHub (https://github.com) and GitHub Enterprise usage. + #[serde(default)] + pub github_account_id: Option, + + /// Date of when this connection was inserted to the database. + pub created_at: DateTime, + + /// Date of when the server has last updated this user's connections. + pub updated_at: DateTime, + + /// Snowflake of the user that owns this connections object. + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +#[derive(Debug, Clone, Default, ToSchema, Serialize, Deserialize, FromRow)] +pub struct Repository { + /// Short description about this user, can be `null` if none was provided. + #[serde(default)] + pub description: Option, + + /// Whether if this repository is deprecated or not + #[serde(default)] + pub deprecated: bool, + + /// Date of when this repository was registered to this instance + pub created_at: DateTime, + + /// Date of when the server has last updated this repository + pub updated_at: DateTime, + + /// Unique hash to locate a repository's icon, this also includes the extension that this avatar is, i.e, `png`. + #[serde(default)] + pub icon_hash: Option, + + /// Whether if this repository is private or not + #[serde(default)] + pub private: bool, + + /// Unique identifier that points to a User or Organization resource that owns this repository + #[schema(schema_with = snowflake_schema)] + pub owner: i64, + + /// Unique [Name] to locate this repository from the API + pub name: Name, + + /// The chart type that this repository is + pub r#type: ChartType, + + /// Unique identifier to locate this repository from the API + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +/// Represents a resource that contains a release from a [Repository] release. Releases +/// are a way to group releases of new versions of Helm charts that can be easily +/// fetched from the API server. +/// +/// Any repository can have an unlimited amount of releases, but tags cannot clash +/// into each other, so the API server will not accept it. Each tag should be +/// a SemVer 2 comformant string, parsing is related to how Cargo evaluates SemVer 2 tags. +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, FromRow)] +pub struct RepositoryRelease { + /// Whether if this release is a pre-release or not. + #[serde(default)] + pub is_prerelease: bool, + + /// Markdown-formatted string that contains a changelog of this release. + #[serde(default)] + pub update_test: Option, + + /// Date of when this release was registered to this instance + pub created_at: DateTime, + + /// Date of when the server has last updated this repository release + pub updated_at: DateTime, + + /// SemVer 2 comformant string that represents this tag. + pub tag: Version, + + /// Unique identifier to locate this repository release resource from the API. + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +/// Represents a resource that is correlated to a repository or organization member +/// that can control the repository's metadata. +#[derive(Debug, Clone, Default, Serialize, Deserialize, ToSchema, FromRow)] +pub struct Member { + /// Display name for this member. This should be formatted as '[{display_name}][Member::display_name] (@[{username}][User::username])' if this + /// is set, otherwise '@[{username}][User::username]' is used. + pub display_name: Option, + + /// Bitfield value of this member's permissions. + pub permissions: u64, + + /// Date-time of when this member resource was last updated by the API server. + pub updated_at: DateTime, + + /// Date-time of when this member resource was created by the API server. + pub joined_at: DateTime, + + /// [User] resource that this member is. + pub user: User, + + /// Unique identifier to locate this member with the API + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +impl Member { + /// Returns a new [`Bitfield`], but this member's permissions + /// are filled in for the bitfield. + /// + /// ## Example + /// ``` + /// # use charted_common::models::entities::Member; + /// # + /// let member = Member::default(); + /// assert_eq!(member.bitfield().bits(), 0); + /// ``` + pub fn bitfield<'a>(&self) -> MemberPermissions<'a> { + MemberPermissions::init(self.permissions) + } +} + +/// Represents a unified entity that can manage and own repositories outside +/// a User. Organizations to the server is used for business-related Helm charts +/// that aren't tied to a specific User. +#[derive(Debug, Clone, ToSchema, Serialize, Deserialize, Default, FromRow)] +pub struct Organization { + /// Whether if this Organization is a Verified Publisher or not. + #[serde(default)] + pub verified_publisher: bool, + + /// Returns the twitter handle for this organization, if populated. + #[serde(default)] + pub twitter_handle: Option, + + /// Valid email address that points to a Gravatar avatar, or `null` if it shouldn't use one as the primary avatar + #[serde(default)] + pub gravatar_email: Option, + + /// Display name for this organization. It should be formatted as '[{display_name}][Organization::display_name] (@[{name}][Organization::name])' + /// or '@[{name}][Organization::name]'. + #[serde(default)] + pub display_name: Option, + + /// Date of when this organization was registered to this instance + pub created_at: DateTime, + + /// Date of when the server has last updated this organization + pub updated_at: DateTime, + + /// Unique hash to locate an organization's icon, this also includes the extension that this icon is, i.e, `png`. + #[serde(default)] + pub icon_hash: Option, + + /// Whether this organization is private and only its member can access this resource. + #[serde(default)] + pub private: bool, + + /// The User resource that owns this organization + pub owner: User, + + /// The name for this organization. + pub name: String, + + /// Unique identifier to locate this organization with the API + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +/// A resource for personal-managed API tokens that is created by a User. This is useful +/// for command line tools or scripts that need to interact with charted-server, but +/// the main use-case is for the [Helm plugin](https://charts.noelware.org/docs/helm-plugin/current). +#[derive(Debug, Clone, Default, ToSchema, Serialize, Deserialize, FromRow)] +pub struct ApiKey { + /// Short description about this API key. + #[serde(default)] + pub description: Option, + + /// Date-time of when this API token expires in, `null` can be returned + /// if the token doesn't expire + #[serde(default)] + pub expires_in: Option, + + /// The scopes that are attached to this API key resource. + pub scopes: i64, + + /// The token itself. This is never revealed when querying, but only revealed + /// when you create the token. + #[serde(default)] + pub token: Option, + + /// User resource that owns this API key. + pub owner: User, + + /// The name of the API key. + pub name: String, + + /// Unique identifer to locate this resource in the API server. + #[schema(schema_with = snowflake_schema)] + pub id: i64, +} + +impl ApiKey { + /// Returns a new [`Bitfield`], but this member's permissions + /// are filled in for the bitfield. + /// + /// ## Example + /// ``` + /// # use charted_common::models::entities::ApiKey; + /// # + /// let resource = ApiKey::default(); + /// assert_eq!(resource.bitfield().bits(), 0); + /// ``` + pub fn bitfield<'a>(&self) -> ApiKeyScopes<'a> { + ApiKeyScopes::init(self.scopes.try_into().unwrap()) + } +} diff --git a/src/common/models/entities/apikeyscope.rs b/src/common/models/entities/apikeyscope.rs new file mode 100644 index 000000000..fb128fd45 --- /dev/null +++ b/src/common/models/entities/apikeyscope.rs @@ -0,0 +1,376 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![allow(deprecated)] + +use crate::common::bitfield::Bitfield; + +macro_rules! gen_apikeyscopes { + ($( + $(#[$doc:meta])* + $key:ident[$s:literal] => $value:expr; + )*) => { + /// Represents a single API key scope. + #[derive(Clone, Copy, PartialEq)] + #[repr(u64)] + #[allow(clippy::enum_clike_unportable_variant)] // we don't provide support for 32bit systems + pub enum ApiKeyScope { + $( + $(#[$doc])* + $key = $value, + )* + } + + impl ::core::fmt::Debug for ApiKeyScope { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + $( + ApiKeyScope::$key => f.write_fmt(format_args!("ApiKeyScope::{} ({})", stringify!($key), $s)), + )* + } + } + } + + impl ::core::fmt::Display for ApiKeyScope { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + $( + ApiKeyScope::$key => f.write_str($s), + )* + } + } + } + + impl ::core::convert::From for u64 { + fn from(scope: ApiKeyScope) -> u64 { + scope as u64 + } + } + + impl ::serde::ser::Serialize for ApiKeyScope { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_u64((*self).into()) + } + } + + impl<'de> ::serde::de::Deserialize<'de> for ApiKeyScope { + fn deserialize>(deserializer: D) -> Result { + struct ApiKeyScopeVisitor; + impl<'de> ::serde::de::Visitor<'de> for ApiKeyScopeVisitor { + type Value = ApiKeyScope; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("string containing the scope id or a u64 of the raw value") + } + + fn visit_u64(self, value: u64) -> Result { + if value >= u64::MAX { + return Err(::serde::de::Error::custom(format!("value is greater or equal to u64::MAX"))); + } + + let max = ApiKeyScope::max(); + if value > max { + return Err(::serde::de::Error::custom(format!("value is greater than the max element ({max})"))); + } + + let map = ApiKeyScope::as_map(); + let element = map.values().find(|x| ((**x) as u64) == value); + if element.is_none() { + return Err(::serde::de::Error::custom(format!("unable to find value by {value}"))); + } + + Ok(*element.unwrap()) + } + + fn visit_str(self, value: &str) -> Result { + let map = ApiKeyScope::as_map(); + if !map.contains_key(value) { + return Err(::serde::de::Error::custom(format!("scope id [{value}] was not found"))); + } + + Ok(*map.get(value).unwrap()) + } + } + + deserializer.deserialize_any(ApiKeyScopeVisitor) + } + } + + impl ApiKeyScope { + /// Returns the API key scope as its code. + #[inline] + pub const fn as_str(&self) -> &str { + match self { + $( + ApiKeyScope::$key => $s, + )* + } + } + + /// Returns the max element available + #[inline] + pub fn max() -> u64 { + let elems = vec![$($value,)*]; + *elems.iter().max().unwrap() + } + + /// Returns an allocated [`HashMap`](std::collections::HashMap) of all the + /// API key scopes together. + #[inline] + pub fn as_map<'a>() -> ::std::collections::HashMap<&'a str, ApiKeyScope> { + let mut h = ::std::collections::HashMap::new(); + $( + h.insert($s, ApiKeyScope::$key); + )* + + h + } + } + }; +} + +gen_apikeyscopes!( + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + // User Scopes + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + /// Allows the current authenticated user to access metadata about themselves. + UserAccess["user:access"] => 1 << 0; + + /// Allows the authenticated user to patch any user metadata. + UserUpdate["user:update"] => 1 << 1; + + /// Allows to delete the current authenticated user. + UserDelete["user:delete"] => 1 << 2; + + /// Allows the current authenticated user to access their connections like their + /// GitHub or GitLab connected user. + UserConnections["user:connections"] => 1 << 3; + + /// **UNUSED AS OF v0.1.0-beta** + /// + /// Allows the current authenticated user to read from their notifications. + #[allow(unused)] + UserNotifications["user:notifications"] => 1 << 4; + + /// Allows the current authenticated user to update their user avatar. + UserAvatarUpdate["user:avatar:update"] => 1 << 5; + + /// Allows the current authenticated user to list their current sessions. + UserSessionsList["user:sessions:list"] => 1 << 6; + + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + // Repository Scopes + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + /// Allows access through private repositories that the current authenticated user + /// can access, except repositories that they are a member apart of. + RepoAccess["repo:access"] => 1 << 7; + + /// Allows the creation of public or private repositories that will be owned + /// by the current authenticated user. + RepoCreate["repo:create"] => 1 << 8; + + /// Allows the deletion of public or private repositories that will be owned + /// by the current authenticated user. + RepoDelete["repo:delete"] => 1 << 9; + + /// Allows patching a public or private repository that is owned by the current + /// authenticated user. + RepoUpdate["repo:update"] => 1 << 10; + + /// **DEPRECATED AS OF v0.1.0-beta** + /// + /// This is replaced by the `repo:releases:create` API key scope, please + /// use that instead. + #[deprecated(since = "0.1.0-beta", note = "Replaced by ApiKeyScope::RepoReleaseCreate")] + RepoWrite["repo:write"] => 1 << 11; + + /// Allows patching a repository icon that the current authenticated user owns. + RepoIconUpdate["repo:icon:update"] => 1 << 12; + + /// Allows the creation of creating repository releases that the current authenticated + /// user owns. + RepoReleaseCreate["repo:releases:create"] => 1 << 13; + + /// Allows patching repository releases that the current authenticated user owns. + RepoReleaseUpdate["repo:releases:update"] => 1 << 14; + + /// Allows the deletion of repository releases that the current authenticated user owns. + RepoReleaseDelete["repo:releases:delete"] => 1 << 15; + + /// Allows viewing all repository members. + RepoMembersList["repo:members:list"] => 1 << 16; + + /// Allows patching repository member metadata. + RepoMemberUpdate["repo:members:update"] => 1 << 17; + + /// Allows kicking repository members off the repository. + RepoMemberKick["repo:members:kick"] => 1 << 18; + + /// Allows viewing all repository member invites. This scope is only used if the + /// [`charted-emails`](https://github.com/charted-dev/emails) gRPC server is running + /// and configured via the [`config.emails_grpc_endpoint`][emails_grpc_endpoint] + /// configuration key. + /// + /// [emails_grpc_endpoint]: https://charts.noelware.org/docs/server/latest/self-hosting/configuration#emails_grpc_endpoint + RepoMemberInviteAccess["repo:members:invites:access"] => 1 << 19; + + /// **DEPRECTEAD AS OF v0.1.0-beta**: This is unused. + #[deprecated(since = "0.1.0-beta", note = "This is unused.")] + RepoMemberInviteUpdate["repo:members:invites:update"] => 1 << 20; + RepoMemberInviteDelete["repo:members:invites:delete"] => 1 << 21; + RepoWebhookList["repo:webhooks:list"] => 1 << 22; + RepoWebhookCreate["repo:webhooks:create"] => 1 << 23; + RepoWebhookUpdate["repo:webhooks:update"] => 1 << 24; + RepoWebhookDelete["repo:webhooks:delete"] => 1 << 25; + RepoWebhookEventAccess["repo:webhooks:events:access"] => 1 << 26; + RepoWebhookEventDelete["repo:webhooks:events:delete"] => 1 << 27; + + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + // API Key Scopes + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + ApiKeyView["apikeys:view"] => 1 << 28; + ApiKeyCreate["apikeys:create"] => 1 << 29; + ApiKeyDelete["apikeys:delete"] => 1 << 30; + ApiKeyUpdate["apikeys:update"] => 1 << 31; + + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + // Organization Scopes + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + OrgAccess["org:access"] => 1 << 32; + OrgCreate["org:create"] => 1 << 33; + OrgUpdate["org:update"] => 1 << 34; + OrgDelete["org:delete"] => 1 << 35; + OrgMemberInvites["org:members:invites"] => 1 << 36; + OrgMemberList["org:members:list"] => 1 << 37; + OrgMemberKick["org:members:kick"] => 1 << 38; + OrgMemberUpdate["org:members:update"] => 1 << 39; + OrgWebhookList["org:webhooks:list"] => 1 << 40; + OrgWebhookCreate["org:webhooks:create"] => 1 << 41; + OrgWebhookUpdate["org:webhooks:update"] => 1 << 42; + OrgWebhookDelete["org:webhooks:delete"] => 1 << 43; + OrgWebhookEventList["org:webhooks:events:list"] => 1 << 44; + OrgWebhookEventDelete["org:webhooks:events:delete"] => 1 << 45; + + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + // Administration Scopes + // +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+ + AdminStats["admin:stats"] => 1 << 46; + AdminUserCreate["admin:users:create"] => 1 << 47; + AdminUserDelete["admin:users:delete"] => 1 << 48; + AdminUserUpdate["admin:users:update"] => 1 << 49; + AdminOrgDelete["admin:orgs:delete"] => 1 << 50; + AdminOrgUpdate["admin:orgs:update"] => 1 << 51; +); + +/// Represents a [`Bitfield`] for managing [`ApiKeyScope`]s. +#[derive(Debug, Clone)] +pub struct ApiKeyScopes<'a>(Bitfield<'a>); +impl<'a> Default for ApiKeyScopes<'a> { + fn default() -> Self { + Self::init(0) + } +} + +impl<'a> ApiKeyScopes<'a> { + /// Initializes a possible empty [`ApiKeyScopes`] bitfield with the given bits. + pub fn init(bits: u64) -> ApiKeyScopes<'a> { + let map = ApiKeyScope::as_map(); + + ApiKeyScopes(Bitfield::new( + bits, + map.iter().map(|(k, v)| (*k, (*v) as u64)).collect(), + )) + } +} + +impl<'a> std::ops::Deref for ApiKeyScopes<'a> { + type Target = Bitfield<'a>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> std::ops::DerefMut for ApiKeyScopes<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde::{Deserialize, Serialize}; + + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct Weow { + scope: ApiKeyScope, + } + + #[test] + fn apikeyscope_serialize() { + let scope = Weow { + scope: ApiKeyScope::UserAccess, + }; + + let serialized = serde_json::to_string(&scope).unwrap(); + assert_eq!("{\"scope\":1}", serialized); + } + + #[test] + fn apikeyscope_deserialize_u64() { + let deserialized: Weow = serde_json::from_str(r#"{"scope":274877906944}"#).unwrap(); + let expected = Weow { + scope: ApiKeyScope::OrgMemberKick, + }; + + assert_eq!(expected, deserialized); + } + + #[test] + #[should_panic(expected = "unable to find value by 7")] + fn apikeyscope_deserialize_nonexisting_u64() { + serde_json::from_str::(r#"{"scope":7}"#).unwrap(); + } + + #[test] + #[should_panic(expected = "value is greater or equal to u64::MAX")] + fn apikeyscope_deserialize_max_u64() { + let weow = u64::MAX; + serde_json::from_str::(format!("{{\"scope\":{weow}}}").as_str()).unwrap(); + } + + #[test] + #[should_panic] // we can't do "expected =" as new scopes can be added and it'll be nondeterministic (unlike the rest of should_panic for u64 variants) + fn apikeyscope_deserialize_max_scope() { + let max = ApiKeyScope::max() + 1; + serde_json::from_str::(format!("{{\"scope\":{max}}}").as_str()).unwrap(); + } + + #[test] + fn apikeyscope_deserialize_str() { + let deserialized: Weow = serde_json::from_str(r#"{"scope":"user:access"}"#).unwrap(); + let expected = Weow { + scope: ApiKeyScope::UserAccess, + }; + + assert_eq!(expected, deserialized); + } + + #[test] + #[should_panic(expected = "scope id [weow fluff] was not found")] + fn apikeyscope_deserialize_nonexisting_str() { + serde_json::from_str::("{\"scope\":\"weow fluff\"}").unwrap(); + } +} diff --git a/src/common/models/entities/member_permissions.rs b/src/common/models/entities/member_permissions.rs new file mode 100644 index 000000000..c360baa40 --- /dev/null +++ b/src/common/models/entities/member_permissions.rs @@ -0,0 +1,213 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::common::bitfield::Bitfield; + +macro_rules! gen_member_permissions { + ($( + $(#[$doc:meta])* + $key:ident[$s:literal] => $value:expr; + )*) => { + /// Represents a single member permission. + #[derive(Clone, Copy, PartialEq)] + #[allow(clippy::enum_clike_unportable_variant)] // we don't provide support for 32bit systems + #[repr(u64)] + pub enum MemberPermission { + $( + $(#[$doc])* + $key = $value, + )* + } + + impl ::core::fmt::Debug for MemberPermission { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + $( + MemberPermission::$key => f.write_fmt(format_args!("MemberPermission::{} ({})", stringify!($key), $s)), + )* + } + } + } + + impl ::core::fmt::Display for MemberPermission { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + match self { + $( + MemberPermission::$key => f.write_str($s), + )* + } + } + } + + impl ::core::convert::From for u64 { + fn from(perm: MemberPermission) -> u64 { + perm as u64 + } + } + + impl ::serde::ser::Serialize for MemberPermission { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_u64((*self).into()) + } + } + + impl<'de> ::serde::de::Deserialize<'de> for MemberPermission { + fn deserialize>(deserializer: D) -> Result { + struct MemberPermissionVisitor; + impl<'de> ::serde::de::Visitor<'de> for MemberPermissionVisitor { + type Value = MemberPermission; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("string containing the scope id or a u64 of the raw value") + } + + fn visit_u64(self, value: u64) -> Result { + if value >= u64::MAX { + return Err(::serde::de::Error::custom(format!("value is greater or equal to u64::MAX"))); + } + + let max = MemberPermission::max(); + if value > max { + return Err(::serde::de::Error::custom(format!("value is greater than the max element ({max})"))); + } + + let map = MemberPermission::as_map(); + let element = map.values().find(|x| ((**x) as u64) == value); + if element.is_none() { + return Err(::serde::de::Error::custom(format!("unable to find value by {value}"))); + } + + Ok(*element.unwrap()) + } + + fn visit_str(self, value: &str) -> Result { + let map = MemberPermission::as_map(); + if !map.contains_key(value) { + return Err(::serde::de::Error::custom(format!("scope id [{value}] was not found"))); + } + + Ok(*map.get(value).unwrap()) + } + } + + deserializer.deserialize_any(MemberPermissionVisitor) + } + } + + impl MemberPermission { + /// Returns the API key scope as its code. + #[inline] + pub const fn as_str(&self) -> &str { + match self { + $( + MemberPermission::$key => $s, + )* + } + } + + /// Returns the max element available + #[inline] + pub fn max() -> u64 { + let elems = vec![$($value,)*]; + *elems.iter().max().unwrap() + } + + /// Returns an allocated [`HashMap`](std::collections::HashMap) of all the + /// API key scopes together. + #[inline] + pub fn as_map<'a>() -> ::std::collections::HashMap<&'a str, MemberPermission> { + let mut h = ::std::collections::HashMap::new(); + $( + h.insert($s, MemberPermission::$key); + )* + + h + } + } + }; +} + +gen_member_permissions!( + /// This member has permission to invite new members into this repository or organization + /// and can view all other pending invites. + MemberInvite["member:invite"] => 1 << 0; + + /// This member has the permission to update any other member's permissions + MemberUpdate["member:update"] => 1 << 1; + + /// This member has the permission to kick other members from the repository or organization + MemberKick["member:kick"] => 1 << 2; + + /// This member has permission to update any repository or organization metadata + MetadataUpdate["metadata:update"] => 1 << 3; + + /// > This is only for organization members, this will be nop for repository members + /// + /// This member has permission to create repositories in an organization. + RepoCreate["repo:create"] => 1 << 4; + + /// > This is only for organization members, this will be nop for repository members + /// + /// This member has permission to delete repositories in an organization. + RepoDelete["repo:delete"] => 1 << 5; + + /// This member has permission to create additional repository or organization + /// webhooks. + WebhookCreate["webhooks:create"] => 1 << 6; + + /// This member has permission to update repository or organization webhooks. + WebhookUpdate["webhooks:update"] => 1 << 7; + + /// This member has permission to delete additional repository or organization webhooks. + WebhookDelete["webhooks:delete"] => 1 << 8; + + /// This member has permission to delete external metadata in an organization + /// or repository, like repository releases + MetadataDelete["metadata:delete"] => 1 << 9; +); + +/// Represents a [`Bitfield`] for managing [`ApiKeyScope`]s. +#[derive(Debug, Clone)] +pub struct MemberPermissions<'a>(Bitfield<'a>); +impl<'a> Default for MemberPermissions<'a> { + fn default() -> Self { + Self::init(0) + } +} + +impl<'a> MemberPermissions<'a> { + /// Initializes a possible empty [`MemberPermissions`] bitfield with the given bits. + pub fn init(bits: u64) -> MemberPermissions<'a> { + let map = MemberPermission::as_map(); + + MemberPermissions(Bitfield::new( + bits, + map.iter().map(|(k, v)| (*k, (*v) as u64)).collect(), + )) + } +} + +impl<'a> std::ops::Deref for MemberPermissions<'a> { + type Target = Bitfield<'a>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> std::ops::DerefMut for MemberPermissions<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/src/common/models/helm.rs b/src/common/models/helm.rs new file mode 100644 index 000000000..cbb4fd50a --- /dev/null +++ b/src/common/models/helm.rs @@ -0,0 +1,370 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::DateTime; +use crate::hashmap; +use chrono::Local; +use semver::{Version, VersionReq}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, str::FromStr}; +use utoipa::{ + openapi::{ + schema::{AdditionalProperties, ObjectBuilder, Schema}, + ArrayBuilder, KnownFormat, Ref, RefOr, SchemaFormat, SchemaType, + }, + ToSchema, +}; + +/// The apiVersion field should be v2 for Helm charts that require at least Helm 3. Charts supporting previous +/// Helm versions have an apiVersion set to v1 and are still installable by Helm 3. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)] +#[serde(rename_all = "lowercase")] +pub enum ChartSpecVersion { + /// Chart supports running on Helm 2 or 3. + V1, + + /// Chart supports running only on Helm 3. + #[default] + V2, +} + +impl<'s> ToSchema<'s> for ChartSpecVersion { + fn schema() -> (&'s str, RefOr) { + ( + "ChartSpecVersion", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .schema_type(SchemaType::String) + .description(Some("The apiVersion field should be v2 for Helm charts that require at least Helm 3. Charts supporting previous Helm versions have an apiVersion set to v1 and are still installable by Helm 3.")) + .default(Some("v2".into())) + .enum_values(Some(vec!["v1", "v2"])) + .build(), + )), + ) + } +} + +/// Represents what type this chart is. Do note that [`ChartType::Operator`] is not supported +/// by Helm, but specific to the API server, this will be switched to [`ChartType::Application`] +/// when serializing to valid Helm objects +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord, sqlx::Type)] +#[sqlx(type_name = "chart_type", rename_all = "lowercase")] +#[serde(rename_all = "lowercase")] +pub enum ChartType { + /// Default chart type and represents a standard chart which can operate on a Kubernetes + /// cluster and spawn in Kubernetes objects. + /// + /// **Note**: Application charts can also act as library charts, just set this to [`Library`][ChartType::Library], + /// and it'll act like a library chart instead. + #[default] + Application, + + /// Library charts provide utilities or functions for building Helm charts, it differs + /// from an [`Application`][ChartType::Application] chart because it cannot create Kubernetes + /// objects from `helm install`. + Library, + + /// Operator is a "non standard" Chart type, and is replaced by [`Application`][ChartType::Application] + /// in releases. This can also be set with the `charts.noelware.org/type` annotation to be `operator` to have + /// the same affect. + Operator, +} + +impl<'s> ToSchema<'s> for ChartType { + fn schema() -> (&'s str, RefOr) { + ( + "ChartType", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .schema_type(SchemaType::String) + .description(Some("Represents what type this chart is. Do keep in mind that `operator` is not supported by Helm, but is specific to the API server. For serializing to valid Helm objects, `application` will be the replacement.")) + .default(Some("application".into())) + .enum_values(Some(vec!["application", "library", "operator"])) + .build(), + )), + ) + } +} + +impl FromStr for ChartType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "application" => Ok(ChartType::Application), + "operator" => Ok(ChartType::Operator), + "library" => Ok(ChartType::Library), + _ => Err(format!("Unknown chart type: {s}")), + } + } +} + +/// ImportValues hold the mapping of source values to parent key to be imported. Each +/// item can be a child/parent sublist item or a string. +#[derive(Debug, Clone, Default, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +pub struct ImportValue { + /// The destination path in the parent chart's values. + pub parent: String, + + /// The source key of the values to be imported + pub child: String, +} + +/// Union enum that can contain a String or a [ImportValue] as the import source +/// for referencing parent key items to be imported. +#[derive(Debug, Clone, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(untagged)] +pub enum StringOrImportValue { + /// String that points to a key to be imported. + String(String), + + /// Parent/child sublist item. + ImportValue(ImportValue), +} + +/// In Helm, one chart may depend on any number of other charts. These dependencies can be dynamically linked using the dependencies' +/// field in Chart.yaml or brought in to the charts/ directory and managed manually. The charts required by the current chart are defined +/// as a list in the dependencies field. +#[derive(Debug, Clone, Default, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +pub struct ChartDependency { + /// The name of the chart + pub name: String, + + /// The version of the chart. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub version: Option, + + /// Repository URL or alias that should be used to grab + /// the dependency from. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub repository: Option, + + /// YAML path that resolves to a boolean to enable or disable charts + /// dynamically. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub condition: Option, + + /// List of tags that can be used to group charts to enable/disable together. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub tags: Vec, + + /// [`ImportValues`][ImportValue] holds the mapping of source values to parent key to be imported. + /// Each item can be a string or pair of child/parent sublist items. + #[serde(default, rename = "import-values", skip_serializing_if = "Vec::is_empty")] + pub import_values: Vec, + + /// Alias that is used to identify a chart. Useful for pointing to the + /// same chart multiple times + #[serde(default, skip_serializing_if = "Option::is_none")] + pub alias: Option, +} + +/// Name and URL/email address combination as a maintainer. [ChartMaintainer::name] can be referenced +/// as a `NameOrSnowflake` union. +#[derive(Debug, Clone, Default, Serialize, Deserialize, ToSchema, PartialEq, Eq, PartialOrd, Ord)] +pub struct ChartMaintainer { + /// The maintainer's name + pub name: String, + + /// The maintainer's email + #[serde(default, skip_serializing_if = "Option::is_none")] + pub email: Option, + + /// URL for the maintainer + #[serde(default, skip_serializing_if = "Option::is_none")] + pub url: Option, +} + +/// Represents the skeleton of a `Chart.yaml` file. +#[derive(Debug, Clone, ToSchema, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct Chart { + /// The `apiVersion` field should be v2 for Helm charts that require at least Helm 3. Charts supporting previous + /// Helm versions have an apiVersion set to v1 and are still installable by Helm 3. + pub api_version: ChartSpecVersion, + + /// The name of the chart. + pub name: String, + + /// A SemVer 2 conformant version string of the chart. + pub version: Version, + + /// The optional `kubeVersion` field can define SemVer constraints on supported Kubernetes versions. + /// Helm will validate the version constraints when installing the chart and fail if the + /// cluster runs an unsupported Kubernetes version. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub kube_version: Option, + + /// A single-sentence description of this project + #[serde(default, skip_serializing_if = "Option::is_none")] + pub description: Option, + + /// The type of the chart. + #[serde(rename = "type", default)] + pub r#type: ChartType, + + /// A list of keywords about this project. These keywords can be searched + /// via the /search endpoint if it's enabled. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub keywords: Vec, + + /// The URL of this project's homepage. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub home: Option, + + /// A list of URLs to the source code for this project + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub sources: Vec, + + /// In Helm, one chart may depend on any number of other charts. These dependencies can be dynamically linked using the dependencies' + /// field in Chart.yaml or brought in to the charts/ directory and managed manually. The charts required by the current chart are defined as a list + /// in the dependencies field. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub dependencies: Vec, + + /// A list of name and URL/email address combinations for the maintainer(s) + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub maintainers: Vec, + + /// A URL or an SVG or PNG image to be used as an icon + #[serde(default, skip_serializing_if = "Option::is_none")] + pub icon: Option, + + /// Note that the appVersion field is not related to the version field. It is a way of specifying the version of the + /// application. For example, the drupal chart may have an appVersion: "8.2.1", indicating that the version of Drupal + /// included in the chart (by default) is 8.2.1. This field is informational, and has no impact on chart version calculations. + /// + /// Wrapping the version in quotes is highly recommended. It forces the YAML parser to treat the version number as a string. + /// Leaving it unquoted can lead to parsing issues in some cases. For example, YAML interprets 1.0 as a floating point value, + /// and a git commit SHA like 1234e10 as scientific notation. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub app_version: Option, + + /// When managing charts in a Chart Repository, it is sometimes necessary to deprecate a chart. The optional deprecated field + /// in Chart.yaml can be used to mark a chart as deprecated. If the latest version of a chart in the repository is marked + /// as deprecated, then the chart as a whole is considered to be deprecated. + /// + /// The chart name can be later reused by publishing a newer version that is not marked as deprecated. + #[serde(default)] + pub deprecated: bool, + + /// Mapping of custom metadata that can be used for custom attributes. + /// + /// ### standardized for charted-server + /// * `charts.noelware.org/maintainers` ~ a comma-delimited list of all the maintainers + /// that are mapped by their `Name` or snowflake ID + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub annotations: HashMap, +} + +/// Represents the specification for a Chart.yaml-schema from a `index.yaml` reference. +#[derive(Debug, Clone, ToSchema, Serialize, Deserialize, PartialEq, Eq)] +pub struct ChartIndexSpec { + /// The Chart specification itself, this will be flatten when (de)serializing. + #[serde(flatten)] + pub spec: Chart, + + // not documented in Helm source code, so I can't really + // add documentation here. + // + // https://github.com/helm/helm/blob/main/pkg/repo/index.go#L255 + #[serde(default)] + pub urls: Vec, + + #[serde(default)] + pub created: Option, + + #[serde(default)] + pub removed: bool, + + #[serde(default)] + pub digest: Option, +} + +/// Schema skeleton for a `index.yaml` file, that represents +/// a [`Chart`] index. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct ChartIndex { + pub api_version: String, + pub generated_at: DateTime, + pub entries: HashMap>, +} + +impl Default for ChartIndex { + fn default() -> ChartIndex { + ChartIndex { + api_version: "v1".into(), + generated_at: Local::now(), + entries: hashmap!(), + } + } +} + +impl<'s> ToSchema<'s> for ChartIndex { + fn schema() -> (&'s str, RefOr) { + ( + "ChartIndex", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .description(Some( + "Schema skeleton for a `index.yml` file that represents a Chart index.", + )) + .property( + "api_version", + RefOr::T( + Schema::Object( + ObjectBuilder::new() + .description(Some("API version for the `index.yaml` file. Will be a constant as `v1`.")) + .schema_type(SchemaType::String) + .build() + ) + ) + ) + .required("api_version") + .property( + "generated_at", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .description(Some("DateTime of when this `index.yaml` was last generated. In charted-server, this is relative on when a new chart release was last published.")) + .schema_type(SchemaType::String) + .format(Some(SchemaFormat::KnownFormat(KnownFormat::DateTime))) + .build() + )) + ) + .required("generated_at") + .property( + "entries", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .description(Some("List of all possible entries for this user/organization.")) + .schema_type(SchemaType::Object) + .additional_properties(Some(AdditionalProperties::::RefOr( + RefOr::T(Schema::Array( + ArrayBuilder::new() + .description(Some("Index contents of a repository")) + .unique_items(true) + .items(RefOr::Ref(Ref::from_schema_name("ChartIndexSpec"))) + .build() + )) + ))) + .build() + )) + ) + .build(), + )), + ) + } +} diff --git a/src/common/models/mod.rs b/src/common/models/mod.rs new file mode 100644 index 000000000..8849c5137 --- /dev/null +++ b/src/common/models/mod.rs @@ -0,0 +1,111 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod distribution; +pub use distribution::*; + +mod name; +pub use name::*; + +pub mod entities; +pub mod helm; +pub mod payloads; + +pub type DateTime = chrono::DateTime; + +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use utoipa::{ + openapi::{OneOfBuilder, RefOr, Schema}, + ToSchema, +}; + +use super::ID; + +/// Represents a union enum that can hold a Snowflake ([u64]-based integer) +/// and a Name, which is a String that is validated with the Name regex. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] +#[serde(untagged)] +pub enum NameOrSnowflake { + /// [u64]-based integer that can point to a entity resource. + Snowflake(u64), + + /// Valid UTF-8 string that is used to point to a entity resource. This + /// is mainly used for `idOrName` path parameters in any of the REST + /// API endpoints to help identify a resource by a Name or Snowflake + /// pointer. + /// + /// Names are validated with the following regex: `^([A-z]|-|_|\d{0,9}){1,32}` + Name(Name), +} + +impl Display for NameOrSnowflake { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + NameOrSnowflake::Snowflake(id) => Display::fmt(id, f), + NameOrSnowflake::Name(name) => Display::fmt(name, f), + } + } +} + +impl<'s> ToSchema<'s> for NameOrSnowflake { + fn schema() -> (&'s str, RefOr) { + ( + "NameOrSnowflake", + RefOr::T(Schema::OneOf( + OneOfBuilder::new() + .description(Some("Represents a union enum that can hold a Snowflake and a Name, which is a String that is validated with the Name regex.")) + .item(ID::schema().1) + .item(Name::schema().1) + .build(), + )), + ) + } +} + +impl NameOrSnowflake { + /// Checks if the value is a valid NameOrSnowflake entity. + pub fn is_valid(&self) -> Result<(), String> { + match self { + NameOrSnowflake::Snowflake(flake) => { + if *flake < 15 { + return Err("was not over or equal to 15 in length".into()); + } + + Ok(()) + } + + NameOrSnowflake::Name(s) => Name::check_is_valid(s.to_string()).map_err(|e| format!("{e}")), + } + } +} + +impl From for NameOrSnowflake { + fn from(value: u64) -> NameOrSnowflake { + NameOrSnowflake::Snowflake(value) + } +} + +impl From<&str> for NameOrSnowflake { + fn from(value: &str) -> NameOrSnowflake { + NameOrSnowflake::Name(value.to_string().into()) + } +} + +impl From for NameOrSnowflake { + fn from(value: String) -> NameOrSnowflake { + NameOrSnowflake::Name(value.into()) + } +} diff --git a/src/common/models/name.rs b/src/common/models/name.rs new file mode 100644 index 000000000..07657ed7d --- /dev/null +++ b/src/common/models/name.rs @@ -0,0 +1,360 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::hashmap; +use serde::{ + de::{Deserialize, Visitor}, + ser::Serialize, +}; +use serde_json::{Number, Value}; +use sqlx::{ + database::{HasArguments, HasValueRef}, + encode::IsNull, + error::BoxDynError, + postgres::PgHasArrayType, + Database, Decode, Encode, Type, +}; +use std::{ + borrow::Cow, + fmt::{Debug, Display}, + ops::Deref, + sync::Arc, +}; +use utoipa::{ + openapi::{ObjectBuilder, RefOr, Schema, SchemaType}, + ToSchema, +}; +use validator::{Validate, ValidationError, ValidationErrors}; + +#[derive(Clone)] +pub enum NameError { + /// Variant that the given input had an invalid character. + InvalidCharacter { + input: String, + at: usize, + ch: char, + }, + + ExceededMax(usize), + + /// Variant that the given input was not valid UTF-8. + InvalidUtf8, + Empty, +} + +impl Debug for NameError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::InvalidCharacter { input, at, ch } => f.write_fmt(format_args!( + "invalid input [{input}]: character '{ch}' in index {at} was not a valid character" + )), + + Self::ExceededMax(over) => f.write_fmt(format_args!( + "name went over {over} characters, expected Name to contain 1..=32 in length" + )), + + Self::InvalidUtf8 => f.write_str("received invalid utf-8"), + Self::Empty => f.write_str("name received was empty"), + } + } +} + +impl Display for NameError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::InvalidCharacter { input, at, ch } => f.write_fmt(format_args!( + "invalid input [{input}]: character '{ch}' in index {at} was not a valid character" + )), + + Self::ExceededMax(over) => f.write_fmt(format_args!( + "name went over {over} characters, expected Name to contain 1..=32 in length" + )), + + Self::InvalidUtf8 => f.write_str("received invalid utf-8"), + Self::Empty => f.write_str("name received was empty"), + } + } +} + +impl std::error::Error for NameError {} + +impl NameError { + pub fn code(&self) -> &'static str { + match self { + Self::InvalidCharacter { .. } => "INVALID_NAME", + Self::ExceededMax(_) => "EXCEEDED_NAME_MAX_LENGTH", + Self::InvalidUtf8 => "INVALID_UTF8", + Self::Empty => "EMPTY_NAME", + } + } +} + +/// Name is a valid UTF-8 string that is used to identify a resource from the REST +/// API in a humane fashion. This is meant to help identify a resource without +/// trying to figure out how to calculate their ID. +/// +/// **Name** has a strict ruleset on how it can be parsed: +/// +/// * Only UTF-8 strings are valid. +/// * Only alphanumeric characters, `-`, and `_` are allowed. +/// * They must contain a length of two minimum and 32 maximum. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Name(Arc); +impl Name { + /// Checks whether if the `input` is a valid Name or not. + #[tracing::instrument(name = "charted.name.validate")] + pub fn check_is_valid + Debug>(input: S) -> Result<(), NameError> { + let name = input.as_ref(); + if name.is_empty() { + return Err(NameError::Empty); + } + + if name.len() > 32 { + let over = name.len() - 32; + return Err(NameError::ExceededMax(over)); + } + + std::str::from_utf8(name.as_bytes()).map_err(|_| NameError::InvalidUtf8)?; + + // convert it to lowercase to allow uppercase strings as well + let lower = name.to_lowercase(); + for (at, ch) in lower.chars().enumerate() { + // if the character is alphanumeric (a-z | A-Z | 0-9), then let's + // continue. + if ch.is_alphanumeric() { + continue; + } + + // Names are allowed to have underscores + if ch == '_' { + continue; + } + + // Names are allowed to have dashes + if ch == '-' { + continue; + } + + return Err(NameError::InvalidCharacter { + input: name.to_string(), + at, + ch, + }); + } + + Ok(()) + } + + /// Creates a new [`Name`], but does check if it is a valid Name. You + /// can use the `new_unchecked` method to not check if it is valid. + pub fn new>(input: S) -> Result { + match Name::check_is_valid(input.as_ref()) { + Ok(()) => Ok(Name::new_unchecked(input)), + Err(e) => Err(e), + } + } + + /// Creates a new [`Name`], but doesn't check if the name is valid or not. + pub fn new_unchecked>(input: S) -> Name { + Name(Arc::from(input.as_ref())) + } + + /// Checks whether if this [`Name`] is valid or not. This is useful if this + /// came from the `new_unchecked` method. + pub fn is_valid(&self) -> Result<(), NameError> { + Name::check_is_valid(&self.0) + } + + /// Returns the name as a string slice. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl Deref for Name { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From<&str> for Name { + fn from(value: &str) -> Name { + Name(Arc::from(value)) + } +} + +impl From for Name { + fn from(value: String) -> Self { + Name(Arc::from(value.as_str())) + } +} + +impl Validate for Name { + fn validate(&self) -> Result<(), ValidationErrors> { + let mut errors = ValidationErrors::new(); + match self.is_valid() { + Ok(()) => Ok(()), + Err(e) => { + let mut params = hashmap!(Cow<'_, str>, serde_json::Value); + if let NameError::InvalidCharacter { at, ch, .. } = e { + params.insert(Cow::Borrowed("index"), Value::Number(Number::from(at))); + params.insert(Cow::Borrowed("char"), Value::String(ch.to_string())); + } + + errors.add( + "name", + ValidationError { + code: Cow::Borrowed(e.code()), + message: Some(Cow::Owned(e.to_string())), + params, + }, + ); + + Err(errors) + } + } + } +} + +impl<'s> ToSchema<'s> for Name { + fn schema() -> (&'s str, RefOr) { + ( + "Name", + RefOr::T(Schema::Object( + ObjectBuilder::new() + .schema_type(SchemaType::String) + .description(Some("A valid UTF-8 string that is used to identify a resource from the REST API in a humane fashion. This is meant to help identify a resource without trying to calculate the resource's Snowflake on the first try.")) + .pattern(Some("([A-z]|-|_|\\d{0,9}){1,32}")) + .min_length(Some(1)) + .max_length(Some(32)) + .build() + )) + ) + } +} + +impl Debug for Name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("Name").field(&self.0.deref()).finish() + } +} + +impl Display for Name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self) + } +} + +impl Serialize for Name { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self) + } +} + +impl<'de> Deserialize<'de> for Name { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct NameVisitor; + + impl<'de> Visitor<'de> for NameVisitor { + type Value = Name; + + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("generic string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(Name::new_unchecked(v)) + } + } + + deserializer.deserialize_str(NameVisitor) + } +} + +impl Default for Name { + fn default() -> Self { + Self::new_unchecked("") + } +} + +impl<'q, DB: Database> Encode<'q, DB> for Name +where + String: Encode<'q, DB>, +{ + fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { + >::encode_by_ref(&self.to_string(), buf) + } + + fn produces(&self) -> Option<::TypeInfo> { + >::produces(&self.to_string()) + } + + fn size_hint(&self) -> usize { + >::size_hint(&self.to_string()) + } +} + +impl<'r, DB: Database> Decode<'r, DB> for Name +where + String: Decode<'r, DB>, +{ + fn decode(value: >::ValueRef) -> Result { + >::decode(value).map(Name::from) + } +} + +impl Type for Name +where + String: Type, +{ + fn type_info() -> ::TypeInfo { + >::type_info() + } + + fn compatible(ty: &::TypeInfo) -> bool { + >::compatible(ty) + } +} + +impl PgHasArrayType for Name +where + String: PgHasArrayType, +{ + fn array_type_info() -> sqlx::postgres::PgTypeInfo { + ::array_type_info() + } +} + +#[cfg(test)] +mod tests { + use super::Name; + + #[test] + fn allow_uppercase_letters() { + assert!(Name::new("Noel").is_ok()); + assert!(Name::new("noel123gaming~!").is_err()); + } +} diff --git a/src/common/models/payloads.rs b/src/common/models/payloads.rs new file mode 100644 index 000000000..df0e9257a --- /dev/null +++ b/src/common/models/payloads.rs @@ -0,0 +1,281 @@ +// 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust +// Copyright 2022-2024 Noelware, LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::common::{ + models::{entities::ApiKeyScope, helm::ChartType, Name}, + serde::Duration, +}; +use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; +use validator::Validate; + +/// Represents the payload for creating a new user. +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Validate)] +pub struct CreateUserPayload { + /// User handle to use to identify yourself. + #[schema(value_type = Name)] + pub username: Name, + + /// The password to use when authenticating, this is optional on non-local sessions. + #[schema( + value_type = password, + pattern = "^.*(?=.{8,})(?=.*[a-zA-Z])(?=.*\\d)?(?=.*[!#$%&? \"])?.*$" + )] + #[validate(length(min = 8))] + pub password: Option, + + /// Email address to identify this user + #[validate(email)] + pub email: String, +} + +/// Payload for patching your user metadata. +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Validate)] +pub struct PatchUserPayload { + /// Optional field to update this user's gravatar email. If this user doesn't + /// have an avatar that is used or prefers not to use their previously uploaded + /// avatars and they set their Gravatar email, their Gravatar will be used. + #[validate(email)] + pub gravatar_email: Option, + + /// Short description about this user. If this field was provided, then the + /// description will be overwritten. If this field is `null`, then nothing + /// will happen. If this field is a empty string, then the description + /// will be wiped. + #[validate(length(max = 140))] + pub description: Option, + + /// Updates this user's username. + #[schema(value_type = Name, nullable)] + pub username: Option, + + /// Updates this user's password, if the session manager configured allows it. + #[schema( + value_type = password, + pattern = "^.*(?=.{8,})(?=.*[a-zA-Z])(?=.*\\d)?(?=.*[!#$%&? \"])?.*$" + )] + #[validate(length(min = 8))] + pub password: Option, + + /// Updates this user's email. + #[validate(email)] + pub email: Option, + + /// Updates this user's display name. + #[validate(length(min = 1, max = 64))] + pub name: Option, +} + +/// Payload to login as a user from the `GET /users/login` endpoint for session-based +/// authentication. +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Validate)] +pub struct UserLoginPayload { + /// Password to authenticate as. + #[schema( + value_type = password, + pattern = "^.*(?=.{8,})(?=.*[a-zA-Z])(?=.*\\d)?(?=.*[!#$%&? \"])?.*$" + )] + #[validate(length(min = 8))] + pub password: String, + + /// Username to authenticate as. This is mutually exclusive with `email`. + pub username: Option, + + /// Email to authenticate as. This is mutually exclusive with `username`. + #[validate(email)] + pub email: Option, +} + +/// Payload to create a Repository entity. +#[derive(Debug, Clone, Default, Serialize, Deserialize, ToSchema, Validate)] +pub struct CreateRepositoryPayload { + /// Short description about this repository. + #[serde(default)] + #[validate(length(max = 140))] + pub description: Option, + + /// Whether if this repository is private. + #[serde(default)] + pub private: bool, + + /// The contents of the README that will be displayed on the repository. If you're + /// using charted's official Helm plugin, new releases can update its README and it'll + /// be reflected. + /// + /// This should be valid Markdown, but XSS cross scripting is impossible as scripts + /// in codeblocks or via ` - +
diff --git a/web/package.json b/web/package.json index c306c01c1..669d4e2af 100644 --- a/web/package.json +++ b/web/package.json @@ -12,9 +12,10 @@ "Noelware Team " ], "scripts": { + "generate:openapi": "bun run scripts/openapi.ts", "build": "vite build", "lint": "bun run scripts/eslint.ts", - "dev": "vite", + "dev": "bunx --bun vite", "fmt": "bun run scripts/prettier.ts" }, "dependencies": { @@ -58,6 +59,7 @@ "@intlify/unplugin-vue-i18n": "2.0.0", "@types/bun": "1.0.1", "@types/luxon": "3.3.7", + "@types/markdown-it": "13.0.7", "@types/node": "20.11.4", "@typescript-eslint/eslint-plugin": "6.19.0", "@typescript-eslint/parser": "6.19.0", @@ -70,12 +72,12 @@ "eslint-formatter-codeframe": "7.32.1", "eslint-plugin-vue": "9.19.2", "jsdom": "23.0.1", + "openapi-typescript": "6.7.4", "prettier": "3.2.2", "typescript": "5.3.3", "unplugin-auto-import": "0.17.3", "unplugin-fluent-vue": "1.1.4", "unplugin-vue-components": "0.26.0", - "unplugin-vue-router": "0.7.0", "vite": "5.0.10", "vite-plugin-vue-devtools": "7.0.2", "vite-plugin-vue-layouts": "0.11.0", diff --git a/web/scripts/openapi.ts b/web/scripts/openapi.ts new file mode 100644 index 000000000..e2ab818ec --- /dev/null +++ b/web/scripts/openapi.ts @@ -0,0 +1,64 @@ +/* + * 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust + * Copyright 2022-2024 Noelware, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { fileURLToPath } from 'node:url'; +import { resolve } from 'node:path'; +import * as log from './util/logging'; +import openapi from 'openapi-typescript'; + +const SCHEMA_FILE = resolve(fileURLToPath(new URL('../..', import.meta.url)), 'assets/openapi.json'); + +async function main() { + log.startGroup('generating `openapi.ts`...'); + const file = Bun.file(SCHEMA_FILE); + const dts = await openapi(file.name!, { + supportArrayLength: true, + immutableTypes: true, + commentHeader: [ + '/* eslint-disable */', + '/*', + ' * 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust', + ' * Copyright 2022-2024 Noelware, LLC. ', + ' *', + ' * Licensed under the Apache License, Version 2.0 (the "License");', + ' * you may not use this file except in compliance with the License.', + ' * You may obtain a copy of the License at', + ' *', + ' * http://www.apache.org/licenses/LICENSE-2.0', + ' *', + ' * Unless required by applicable law or agreed to in writing, software', + ' * distributed under the License is distributed on an "AS IS" BASIS,', + ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', + ' * See the License for the specific language governing permissions and', + ' * limitations under the License.', + ' */', + '', + `// This file was generated by \`bun generate:openapi\` at ${new Date().toISOString()}`, + `// Do not make edits to this file as it won't reflect on the next \`bun generate:openapi\` invocation`, + '' + ].join('\n') + }); + + const generated = Bun.file('./src/@types/openapi.generated.d.ts'); + await Bun.write(generated, dts); + log.endGroup(); +} + +main().catch((ex) => { + log.error(ex); + process.exit(1); +}); diff --git a/web/scripts/util/logging.ts b/web/scripts/util/logging.ts index 5d759c371..a8561d200 100644 --- a/web/scripts/util/logging.ts +++ b/web/scripts/util/logging.ts @@ -27,6 +27,16 @@ import { } from '@actions/core'; export const ci = hasOwnProperty(process.env, 'CI') && process.env.CI !== ''; +export const group = (name: string) => { + startGroup(name); + + return { + [Symbol.dispose]: () => { + endGroup(); + } + }; +}; + export const startGroup: typeof __startGroup = (name) => ci ? __startGroup(name) diff --git a/web/src/@types/openapi.generated.d.ts b/web/src/@types/openapi.generated.d.ts new file mode 100644 index 000000000..d980e9905 --- /dev/null +++ b/web/src/@types/openapi.generated.d.ts @@ -0,0 +1,670 @@ +/* eslint-disable */ +/* + * 🐻‍❄️📦 charted-server: Free, open source, and reliable Helm Chart registry made in Rust + * Copyright 2022-2024 Noelware, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file was generated by `bun generate:openapi` at 2024-01-23T03:12:06.183Z +// Do not make edits to this file as it won't reflect on the next `bun generate:openapi` invocation + +export interface paths { + '/': { + /** @description Main entrypoint to charted-server. This is just a generic "hello world" response. */ + get: operations['main']; + }; + '/features': { + /** @description Retrieve this server's features. This is only for enabling or disabling features for API consumers. */ + get: operations['features']; + }; + '/heartbeat': { + /** @description Generic healthcheck endpoint */ + get: operations['heartbeat']; + }; + '/index/{idOrName}': { + /** @description Returns a index of a user or organization's Helm charts */ + get: operations['get_chart_index']; + }; + '/info': { + /** @description REST handler for getting more information about this instance that can be visible for API consumers. */ + get: operations['info']; + }; + '/v1': { + /** @description Main entrypoint to charted-server. This is just a generic "hello world" response. */ + get: operations['main']; + }; + '/v1/features': { + /** @description Retrieve this server's features. This is only for enabling or disabling features for API consumers. */ + get: operations['features']; + }; + '/v1/heartbeat': { + /** @description Generic healthcheck endpoint */ + get: operations['heartbeat']; + }; + '/v1/index/{idOrName}': { + /** @description Returns a index of a user or organization's Helm charts */ + get: operations['get_chart_index']; + }; + '/v1/info': { + /** @description REST handler for getting more information about this instance that can be visible for API consumers. */ + get: operations['info']; + }; +} + +export type webhooks = Record; + +export interface components { + schemas: { + /** + * @description A resource for personal-managed API tokens that is created by a User. This is useful + * for command line tools or scripts that need to interact with charted-server, but + * the main use-case is for the [Helm plugin](https://charts.noelware.org/docs/helm-plugin/current). + */ + readonly ApiKey: { + /** @description Short description about this API key. */ + readonly description?: string | null; + readonly expires_in?: components['schemas']['DateTime'] | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + /** @description The name of the API key. */ + readonly name: string; + readonly owner: components['schemas']['User']; + /** + * Format: int64 + * @description The scopes that are attached to this API key resource. + */ + readonly scopes: number; + /** + * @description The token itself. This is never revealed when querying, but only revealed + * when you create the token. + */ + readonly token?: string | null; + }; + /** @description Represents the skeleton of a `Chart.yaml` file. */ + readonly Chart: { + /** + * @description Mapping of custom metadata that can be used for custom attributes. + * + * ### standardized for charted-server + * * `charts.noelware.org/maintainers` ~ a comma-delimited list of all the maintainers + * that are mapped by their `Name` or snowflake ID + */ + readonly annotations?: { + [key: string]: string; + }; + readonly apiVersion: components['schemas']['ChartSpecVersion']; + /** + * @description Note that the appVersion field is not related to the version field. It is a way of specifying the version of the + * application. For example, the drupal chart may have an appVersion: "8.2.1", indicating that the version of Drupal + * included in the chart (by default) is 8.2.1. This field is informational, and has no impact on chart version calculations. + * + * Wrapping the version in quotes is highly recommended. It forces the YAML parser to treat the version number as a string. + * Leaving it unquoted can lead to parsing issues in some cases. For example, YAML interprets 1.0 as a floating point value, + * and a git commit SHA like 1234e10 as scientific notation. + */ + readonly appVersion?: string | null; + /** + * @description In Helm, one chart may depend on any number of other charts. These dependencies can be dynamically linked using the dependencies' + * field in Chart.yaml or brought in to the charts/ directory and managed manually. The charts required by the current chart are defined as a list + * in the dependencies field. + */ + readonly dependencies?: readonly components['schemas']['ChartDependency'][]; + /** + * @description When managing charts in a Chart Repository, it is sometimes necessary to deprecate a chart. The optional deprecated field + * in Chart.yaml can be used to mark a chart as deprecated. If the latest version of a chart in the repository is marked + * as deprecated, then the chart as a whole is considered to be deprecated. + * + * The chart name can be later reused by publishing a newer version that is not marked as deprecated. + */ + readonly deprecated?: boolean; + /** @description A single-sentence description of this project */ + readonly description?: string | null; + /** @description The URL of this project's homepage. */ + readonly home?: string | null; + /** @description A URL or an SVG or PNG image to be used as an icon */ + readonly icon?: string | null; + /** + * @description A list of keywords about this project. These keywords can be searched + * via the /search endpoint if it's enabled. + */ + readonly keywords?: readonly string[]; + readonly kubeVersion?: components['schemas']['VersionReq'] | null; + /** @description A list of name and URL/email address combinations for the maintainer(s) */ + readonly maintainers?: readonly components['schemas']['ChartMaintainer'][]; + /** @description The name of the chart. */ + readonly name: string; + /** @description A list of URLs to the source code for this project */ + readonly sources?: readonly string[]; + readonly type?: components['schemas']['ChartType']; + readonly version: components['schemas']['Version']; + }; + /** + * @description In Helm, one chart may depend on any number of other charts. These dependencies can be dynamically linked using the dependencies' + * field in Chart.yaml or brought in to the charts/ directory and managed manually. The charts required by the current chart are defined + * as a list in the dependencies field. + */ + readonly ChartDependency: { + /** + * @description Alias that is used to identify a chart. Useful for pointing to the + * same chart multiple times + */ + readonly alias?: string | null; + /** + * @description YAML path that resolves to a boolean to enable or disable charts + * dynamically. + */ + readonly condition?: string | null; + /** + * @description [`ImportValues`][ImportValue] holds the mapping of source values to parent key to be imported. + * Each item can be a string or pair of child/parent sublist items. + */ + readonly 'import-values'?: readonly components['schemas']['StringOrImportValue'][]; + /** @description The name of the chart */ + readonly name: string; + /** + * @description Repository URL or alias that should be used to grab + * the dependency from. + */ + readonly repository?: string | null; + /** @description List of tags that can be used to group charts to enable/disable together. */ + readonly tags?: readonly string[]; + readonly version?: components['schemas']['Version'] | null; + }; + /** @description Schema skeleton for a `index.yml` file that represents a Chart index. */ + readonly ChartIndex: { + /** @description API version for the `index.yaml` file. Will be a constant as `v1`. */ + readonly api_version: string; + /** @description List of all possible entries for this user/organization. */ + readonly entries?: { + [key: string]: readonly components['schemas']['ChartIndexSpec'][]; + }; + /** + * Format: date-time + * @description DateTime of when this `index.yaml` was last generated. In charted-server, this is relative on when a new chart release was last published. + */ + readonly generated_at: string; + }; + /** @description Represents the specification for a Chart.yaml-schema from a `index.yaml` reference. */ + readonly ChartIndexSpec: components['schemas']['Chart'] & { + readonly created?: components['schemas']['DateTime'] | null; + readonly digest?: string | null; + readonly removed?: boolean; + readonly urls?: readonly string[]; + }; + /** + * @description Name and URL/email address combination as a maintainer. [ChartMaintainer::name] can be referenced + * as a `NameOrSnowflake` union. + */ + readonly ChartMaintainer: { + /** @description The maintainer's email */ + readonly email?: string | null; + /** @description The maintainer's name */ + readonly name: string; + /** @description URL for the maintainer */ + readonly url?: string | null; + }; + /** + * @description The apiVersion field should be v2 for Helm charts that require at least Helm 3. Charts supporting previous Helm versions have an apiVersion set to v1 and are still installable by Helm 3. + * @default v2 + * @enum {string} + */ + readonly ChartSpecVersion: 'v1' | 'v2'; + /** + * @description Represents what type this chart is. Do keep in mind that `operator` is not supported by Helm, but is specific to the API server. For serializing to valid Helm objects, `application` will be the replacement. + * @default application + * @enum {string} + */ + readonly ChartType: 'application' | 'library' | 'operator'; + /** + * Format: date-time + * @description RFC3339-encoded string that represents the date time of an entity + */ + readonly DateTime: string; + /** @description Represents an error that could occur. */ + readonly Error: { + readonly code: components['schemas']['ErrorCode']; + /** @description Other details to send to the user to give even more context about this error. */ + readonly details?: unknown; + /** + * @description Humane message that is based off the contextual [error code][Error::code] to give + * a brief description. + */ + readonly message: string; + }; + /** + * @description Represents a error code that can happen. + * @enum {string} + */ + readonly ErrorCode: + | 'INTERNAL_SERVER_ERROR' + | 'REACHED_UNEXPECTED_EOF' + | 'UNABLE_TO_PROCESS' + | 'HANDLER_NOT_FOUND' + | 'ENTITY_NOT_FOUND' + | 'ENTITY_ALREADY_EXISTS' + | 'VALIDATION_FAILED' + | 'UNKNOWN_CDN_QUERY' + | 'INVALID_CONTENT_TYPE' + | 'SESSION_ONLY_ROUTE' + | 'INVALID_HTTP_HEADER' + | 'UNABLE_TO_DECODE_BASE64' + | 'INVALID_UTF8' + | 'INVALID_BODY' + | 'MISSING_HEADER' + | 'REGISTRATIONS_DISABLED' + | 'MISSING_PASSWORD' + | 'ACCESS_NOT_PERMITTED' + | 'IO' + | 'INVALID_JWT_CLAIM' + | 'MISSING_AUTHORIZATION_HEADER' + | 'INVALID_PASSWORD' + | 'INVALID_AUTHENTICATION_TYPE' + | 'INVALID_AUTHORIZATION_PARTS' + | 'INVALID_SESSION_TOKEN' + | 'SESSION_EXPIRED' + | 'UNKNOWN_SESSION' + | 'REFRESH_TOKEN_REQUIRED' + | 'MAX_PER_PAGE_EXCEEDED' + | 'UNABLE_TO_PARSE_PATH_PARAMETER' + | 'MISSING_PATH_PARAMETER' + | 'INVALID_JSON_PAYLOAD' + | 'UNKNOWN_MULTIPART_FIELD' + | 'INCOMPLETE_MULTIPART_FIELD_DATA' + | 'READ_MULTIPART_HEADER_FAILED' + | 'DECODE_MULTIPART_CONTENT_TYPE_FAILED' + | 'MISSING_MULTIPART_BOUNDARY' + | 'NO_MULTIPART_RECEIVED' + | 'INCOMPLETE_MULTIPART_STREAM' + | 'DECODE_MULTIPART_HEADER_NAME_FAILED' + | 'STREAM_SIZE_EXCEEDED' + | 'MULTIPART_FIELDS_SIZE_EXCEEDED' + | 'MULTIPART_STREAM_READ_FAILED' + | 'MISSING_MULTIPART_FIELD' + | 'INVALID_MULTIPART_BOUNDARY'; + /** + * @description ImportValues hold the mapping of source values to parent key to be imported. Each + * item can be a child/parent sublist item or a string. + */ + readonly ImportValue: { + /** @description The source key of the values to be imported */ + readonly child: string; + /** @description The destination path in the parent chart's values. */ + readonly parent: string; + }; + /** @description Represents the response for the `GET /info` REST handler. */ + readonly InfoResponse: { + /** @description Build date in RFC3339 format */ + readonly build_date: string; + /** @description The commit hash from the Git repository. */ + readonly commit_sha: string; + readonly distribution: components['schemas']['Distribution']; + /** @description Product name. Will always be "charted-server" */ + readonly product: string; + /** @description Vendor of charted-server, will always be "Noelware, LLC." */ + readonly vendor: string; + /** @description Valid SemVer 2 of the current version of this instance */ + readonly version: string; + }; + /** @description Response object for the `GET /` REST controller. */ + readonly MainResponse: { + /** @description Documentation URL for this generic entrypoint response. */ + readonly docs: string; + /** @description The message, which will always be "Hello, world!" */ + readonly message: string; + /** @description You know, for Helm charts? */ + readonly tagline: string; + }; + /** + * @description Represents a resource that is correlated to a repository or organization member + * that can control the repository's metadata. + */ + readonly Member: { + /** + * @description Display name for this member. This should be formatted as '[{display_name}][Member::display_name] (@[{username}][User::username])' if this + * is set, otherwise '@[{username}][User::username]' is used. + */ + readonly display_name?: string | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + readonly joined_at: components['schemas']['DateTime']; + /** + * Format: int64 + * @description Bitfield value of this member's permissions. + */ + readonly permissions: number; + readonly updated_at: components['schemas']['DateTime']; + readonly user: components['schemas']['User']; + }; + /** @description A valid UTF-8 string that is used to identify a resource from the REST API in a humane fashion. This is meant to help identify a resource without trying to calculate the resource's Snowflake on the first try. */ + readonly Name: string; + /** @description Represents a union enum that can hold a Snowflake and a Name, which is a String that is validated with the Name regex. */ + readonly NameOrSnowflake: number | string; + /** + * @description The ordering to use when querying paginated REST calls. + * @enum {string} + */ + readonly OrderBy: 'ASC' | 'DESC'; + /** + * @description Represents a unified entity that can manage and own repositories outside + * a User. Organizations to the server is used for business-related Helm charts + * that aren't tied to a specific User. + */ + readonly Organization: { + readonly created_at: components['schemas']['DateTime']; + /** + * @description Display name for this organization. It should be formatted as '[{display_name}][Organization::display_name] (@[{name}][Organization::name])' + * or '@[{name}][Organization::name]'. + */ + readonly display_name?: string | null; + /** @description Valid email address that points to a Gravatar avatar, or `null` if it shouldn't use one as the primary avatar */ + readonly gravatar_email?: string | null; + /** @description Unique hash to locate an organization's icon, this also includes the extension that this icon is, i.e, `png`. */ + readonly icon_hash?: string | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + /** @description The name for this organization. */ + readonly name: string; + readonly owner: components['schemas']['User']; + /** @description Whether this organization is private and only its member can access this resource. */ + readonly private?: boolean; + /** @description Returns the twitter handle for this organization, if populated. */ + readonly twitter_handle?: string | null; + readonly updated_at: components['schemas']['DateTime']; + /** @description Whether if this Organization is a Verified Publisher or not. */ + readonly verified_publisher?: boolean; + }; + /** @description Information about a [pagination][Pagination] page. */ + readonly PageInfo: { + readonly cursor: components['schemas']['Snowflake']; + }; + readonly PaginatedMember: { + readonly data: readonly components['schemas']['Member'][]; + readonly page_info: components['schemas']['PageInfo']; + }; + readonly PaginatedOrganization: { + readonly data: readonly components['schemas']['Organization'][]; + readonly page_info: components['schemas']['PageInfo']; + }; + readonly PaginatedRepository: { + readonly data: readonly components['schemas']['Repository'][]; + readonly page_info: components['schemas']['PageInfo']; + }; + readonly Repository: { + readonly created_at: components['schemas']['DateTime']; + /** @description Whether if this repository is deprecated or not */ + readonly deprecated?: boolean; + /** @description Short description about this user, can be `null` if none was provided. */ + readonly description?: string | null; + /** @description Unique hash to locate a repository's icon, this also includes the extension that this avatar is, i.e, `png`. */ + readonly icon_hash?: string | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + readonly name: components['schemas']['Name']; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly owner: number; + /** @description Whether if this repository is private or not */ + readonly private?: boolean; + readonly type: components['schemas']['ChartType']; + readonly updated_at: components['schemas']['DateTime']; + }; + /** + * @description Represents a resource that contains a release from a [Repository] release. Releases + * are a way to group releases of new versions of Helm charts that can be easily + * fetched from the API server. + * + * Any repository can have an unlimited amount of releases, but tags cannot clash + * into each other, so the API server will not accept it. Each tag should be + * a SemVer 2 comformant string, parsing is related to how Cargo evaluates SemVer 2 tags. + */ + readonly RepositoryRelease: { + readonly created_at: components['schemas']['DateTime']; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + /** @description Whether if this release is a pre-release or not. */ + readonly is_prerelease?: boolean; + readonly tag: components['schemas']['Version']; + /** @description Markdown-formatted string that contains a changelog of this release. */ + readonly update_text?: string | null; + readonly updated_at: components['schemas']['DateTime']; + }; + readonly Session: { + /** + * @description Access token. This will always be `null` if queried, but always will + * be present if you successfully logged in. + */ + readonly access_token?: string | null; + /** + * @description Refresh token. This will always be `null` if queried, but always will + * be present if you successfully logged in. + */ + readonly refresh_token?: string | null; + /** + * Format: uuid + * @description UUID of the session. + */ + readonly session: string; + /** + * Format: int64 + * @description ID of the user that created this session. + */ + readonly user: number; + }; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly Snowflake: number; + /** + * @description Union enum that can contain a String or a [ImportValue] as the import source + * for referencing parent key items to be imported. + */ + readonly StringOrImportValue: string | components['schemas']['ImportValue']; + /** @description Represents an account that can own [repositories][Repository] and [organizations][Organizations] */ + readonly User: { + /** @description Whether if this User is an Administrator of this instance */ + readonly admin?: boolean; + /** @description Unique hash to locate a user's avatar, this also includes the extension that this avatar is, i.e, `png`. */ + readonly avatar_hash?: string | null; + readonly created_at: components['schemas']['DateTime']; + /** @description Short description about this user, can be `null` if none was provided. */ + readonly description?: string | null; + /** @description Valid email address that points to a Gravatar avatar, or `null` if it shouldn't use one as the primary avatar */ + readonly gravatar_email?: string | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + /** @description A valid UTF-8 string that is used to identify a resource from the REST API in a humane fashion. This is meant to help identify a resource without trying to calculate the resource's Snowflake on the first try. */ + readonly name?: string; + readonly updated_at: components['schemas']['DateTime']; + readonly username: components['schemas']['Name']; + /** @description Whether if this User is a Verified Publisher or not. */ + readonly verified_publisher?: boolean; + }; + /** + * @description Represents a collection of a user's connections that can be used + * to login from different sources (like GitHub OAuth2) + */ + readonly UserConnections: { + readonly created_at: components['schemas']['DateTime']; + /** + * @description Account ID that was sourced from GitHub OAuth2. This can differ from + * GitHub (https://github.com) and GitHub Enterprise usage. + */ + readonly github_account_id?: string | null; + /** @description Account ID that was sourced from Google OAuth2 */ + readonly google_account_id?: string | null; + /** + * Format: int64 + * @description Unique identifier for a resource. Based off the [Twitter Snowflake](https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake) spec. + */ + readonly id: number; + /** + * Format: int64 + * @description Snowflake ID that was sourced from [Noelware's Accounts System](https://accounts.noelware.org) + */ + readonly noelware_account_id?: number | null; + readonly updated_at: components['schemas']['DateTime']; + }; + /** @description Represents a semantic version (https://semver.org) that Helm and charted-server will only accept */ + readonly Version: string; + /** @description Represents a semantic version (https://semver.org) requirement (i.e, `>=1.2.0`) that Helm and charted-server will only accept */ + readonly VersionReq: string; + }; + responses: { + /** @description API response that doesn't contain any data */ + readonly ApiErrorResponse: { + content: { + readonly 'application/json': { + /** @description List of errors on why the request failed. */ + readonly errors: readonly components['schemas']['Error'][]; + /** @description whether if this response [ApiErrorResponse] was a success or not */ + readonly success: boolean; + }; + }; + }; + /** @description API response that doesn't contain any data */ + readonly EmptyApiResponse: { + content: { + readonly 'application/json': { + /** @description whether if this response [EmptyApiResponse] was a success or not */ + readonly success: boolean; + }; + }; + }; + /** @description Response object for "InfoResponse" */ + readonly InfoResponse: { + content: { + readonly 'application/json': { + readonly data: components['schemas']['InfoResponse']; + /** @description whether if this response [InfoResponse] was successful or not */ + readonly success: boolean; + }; + }; + }; + /** @description Response object for "MainResponse" */ + readonly MainResponse: { + content: { + readonly 'application/json': { + readonly data: components['schemas']['MainResponse']; + /** @description whether if this response [MainResponse] was successful or not */ + readonly success: boolean; + }; + }; + }; + }; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} + +export type $defs = Record; + +export type external = Record; + +export interface operations { + /** @description Main entrypoint to charted-server. This is just a generic "hello world" response. */ + main: { + responses: { + /** @description Successful response */ + 200: { + content: { + readonly 'application/json': components['responses']['MainResponse']; + }; + }; + }; + }; + /** @description Retrieve this server's features. This is only for enabling or disabling features for API consumers. */ + features: { + responses: { + /** @description Successful response */ + 200: { + content: { + readonly 'application/json': components['responses']['FeaturesResponse']; + }; + }; + }; + }; + /** @description Generic healthcheck endpoint */ + heartbeat: { + responses: { + /** @description Successful response */ + 200: { + content: { + readonly 'text/plain': string; + }; + }; + }; + }; + /** @description Returns a index of a user or organization's Helm charts */ + get_chart_index: { + parameters: { + path: { + /** @description Path parameter that can take a `Name` or `Snowflake` identifier */ + idOrName: components['schemas']['NameOrSnowflake']; + }; + }; + responses: { + /** @description Chart index for a specific user or organization */ + 200: { + content: { + readonly 'text/yaml': components['responses']['ChartIndexResponse']; + }; + }; + /** @description User or Organization was not found */ + 404: { + content: { + readonly 'application/json': components['responses']['ApiErrorResponse']; + }; + }; + /** @description Internal Server Error */ + 500: { + content: { + readonly 'application/json': components['responses']['ApiErrorResponse']; + }; + }; + }; + }; + /** @description REST handler for getting more information about this instance that can be visible for API consumers. */ + info: { + responses: { + /** @description Successful response */ + 200: { + content: { + readonly 'application/json': components['responses']['InfoResponse']; + }; + }; + }; + }; +} diff --git a/web/src/App.vue b/web/src/App.vue index 7590c00b2..7d0a1f171 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -16,13 +16,9 @@ --> + + + diff --git a/web/src/components/ErrorBoundary.vue b/web/src/components/ErrorBoundary.vue deleted file mode 100644 index 4d20b3b4e..000000000 --- a/web/src/components/ErrorBoundary.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - - - diff --git a/web/src/components/ui/toast/Title.vue b/web/src/components/Markdown.vue similarity index 54% rename from web/src/components/ui/toast/Title.vue rename to web/src/components/Markdown.vue index 81e998b0b..da8440106 100644 --- a/web/src/components/ui/toast/Title.vue +++ b/web/src/components/Markdown.vue @@ -15,16 +15,35 @@ ~ limitations under the License. --> - - + + diff --git a/web/src/components/ui/AppShell.vue b/web/src/components/ui/Shell.vue similarity index 89% rename from web/src/components/ui/AppShell.vue rename to web/src/components/ui/Shell.vue index a366e3320..029be179f 100644 --- a/web/src/components/ui/AppShell.vue +++ b/web/src/components/ui/Shell.vue @@ -18,10 +18,6 @@